LCOV - code coverage report
Current view: top level - EnergyPlus - SolarShading.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 53.7 % 6175 3313
Test Date: 2025-06-02 12:03:30 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) {
     207          112 :             DisplayString(state, "Allocate Solar Module Arrays");
     208              :         }
     209          114 :         AllocateModuleArrays(state);
     210              : 
     211          114 :         if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::FullInteriorExterior) {
     212          104 :             if (state.dataSolarShading->firstTime) {
     213          102 :                 DisplayString(state, "Computing Interior Solar Absorption Factors");
     214              :             }
     215          104 :             ComputeIntSolarAbsorpFactors(state);
     216              :         }
     217              : 
     218          114 :         if (state.dataSolarShading->firstTime) {
     219          112 :             DisplayString(state, "Determining Shadowing Combinations");
     220              :         }
     221          114 :         DetermineShadowingCombinations(state);
     222          114 :         state.dataSolarShading->shd_stream.reset(); // Done writing to shd file
     223              : 
     224          114 :         if (state.dataSolarShading->firstTime) {
     225          112 :             DisplayString(state, "Computing Window Shade Absorption Factors");
     226              :         }
     227          114 :         ComputeWinShadeAbsorpFactors(state);
     228              : 
     229          114 :         if (s_surf->CalcSolRefl) {
     230            0 :             DisplayString(state, "Initializing Solar Reflection Factors");
     231            0 :             InitSolReflRecSurf(state);
     232              :         }
     233              : 
     234          114 :         if (state.dataSolarShading->firstTime) {
     235          112 :             DisplayString(state, "Proceeding with Initializing Solar Calculations");
     236              :         }
     237              :     }
     238              : 
     239          119 :     if (state.dataGlobal->BeginEnvrnFlag) {
     240          107 :         state.dataSolarShading->SurfSunCosTheta = 0.0;
     241          107 :         state.dataSolarShading->SurfSunlitArea = 0.0;
     242          107 :         s_surf->SurfSunlitArea = 0.0;
     243          107 :         s_surf->SurfSunlitFrac = 0.0;
     244          107 :         state.dataHeatBal->SurfSunlitFracHR = 0.0;
     245          107 :         state.dataHeatBal->SurfSunlitFrac = 0.0;
     246          107 :         state.dataHeatBal->SurfSunlitFracWithoutReveal = 0.0;
     247          107 :         state.dataHeatBal->SurfWinBackSurfaces = 0;
     248          107 :         state.dataHeatBal->SurfWinOverlapAreas = 0.0;
     249          107 :         state.dataHeatBal->SurfCosIncAngHR = 0.0;
     250          107 :         state.dataHeatBal->SurfCosIncAng = 0.0;
     251          107 :         state.dataSolarShading->SurfAnisoSkyMult = 1.0; // For isotropic sky; recalculated in AnisoSkyViewFactors if anisotropic radiance
     252              :         //    WithShdgIsoSky=0.0
     253              :         //    WoShdgIsoSky=0.0
     254              :         //    WithShdgHoriz=0.0
     255              :         //    WoShdgHoriz=0.0
     256              :         //    DifShdgRatioIsoSky=0.0
     257              :         //    DifShdgRatioHoriz=0.0
     258          107 :         state.dataSolarShading->SurfMultIsoSky = 0.0;
     259          107 :         state.dataSolarShading->SurfMultCircumSolar = 0.0;
     260          107 :         state.dataSolarShading->SurfMultHorizonZenith = 0.0;
     261          107 :         state.dataSolarShading->SurfWinRevealStatus = 0;
     262              : 
     263          234 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
     264          127 :             state.dataHeatBal->ZoneWinHeatGain(zoneNum) = 0.0;
     265          127 :             state.dataHeatBal->ZoneWinHeatGainRep(zoneNum) = 0.0;
     266          127 :             state.dataHeatBal->ZoneWinHeatLossRep(zoneNum) = 0.0;
     267          127 :             state.dataHeatBal->ZoneWinHeatGainRepEnergy(zoneNum) = 0.0;
     268          127 :             state.dataHeatBal->ZoneWinHeatLossRepEnergy(zoneNum) = 0.0;
     269          127 :             state.dataHeatBal->ZoneOpaqSurfInsFaceCond(zoneNum) = 0.0;
     270          127 :             state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(zoneNum) = 0.0;
     271          127 :             state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(zoneNum) = 0.0;
     272          127 :             state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(zoneNum) = 0.0;
     273          127 :             state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(zoneNum) = 0.0;
     274              :         }
     275          242 :         for (int enclNum = 1; enclNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclNum) {
     276          135 :             state.dataHeatBal->ZoneTransSolar(enclNum) = 0.0;
     277          135 :             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclNum) = 0.0;
     278          135 :             state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclNum) = 0.0;
     279          135 :             state.dataHeatBal->EnclSolInitialDifSolReflW(enclNum) = 0.0;
     280          135 :             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclNum) = 0.0;
     281          135 :             state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclNum) = 0.0;
     282          135 :             state.dataHeatBal->ZoneTransSolarEnergy(enclNum) = 0.0;
     283          135 :             state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclNum) = 0.0;
     284          135 :             state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclNum) = 0.0;
     285          135 :             state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclNum) = 0.0;
     286          135 :             state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclNum) = 0.0;
     287              :         }
     288          876 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
     289          769 :             state.dataHeatBal->SurfQRadSWOutIncident(SurfNum) = 0.0;
     290          769 :             state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfNum) = 0.0;
     291          769 :             state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
     292          769 :             state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = 0.0;
     293          769 :             state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfNum) = 0.0;
     294          769 :             state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfNum) = 0.0;
     295          769 :             state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfNum) = 0.0;
     296          769 :             state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfNum) = 0.0;
     297          769 :             state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfNum) = 0.0;
     298          769 :             state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfNum) = 0.0;
     299          769 :             state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfNum) = 0.0;
     300          769 :             state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfNum) = 0.0;
     301          769 :             state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfNum) = 0.0;
     302          769 :             state.dataHeatBal->SurfCosIncidenceAngle(SurfNum) = 0.0;
     303          769 :             state.dataHeatBal->SurfSWInAbsTotalReport(SurfNum) = 0.0;
     304          769 :             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
     305          769 :             state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
     306          769 :             state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfNum) = 0.0;
     307              :         }
     308          234 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
     309          271 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
     310          144 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     311          144 :                 int const firstSurfWin = thisSpace.WindowSurfaceFirst;
     312          144 :                 int const lastSurfWin = thisSpace.WindowSurfaceLast;
     313          190 :                 for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
     314              : 
     315           46 :                     s_surf->SurfWinTransSolar(SurfNum) = 0.0;
     316           46 :                     s_surf->SurfWinBmSolar(SurfNum) = 0.0;
     317           46 :                     s_surf->SurfWinBmBmSolar(SurfNum) = 0.0;
     318           46 :                     s_surf->SurfWinBmDifSolar(SurfNum) = 0.0;
     319           46 :                     s_surf->SurfWinDifSolar(SurfNum) = 0.0;
     320              : 
     321           46 :                     s_surf->SurfWinTransSolarEnergy(SurfNum) = 0.0;
     322           46 :                     s_surf->SurfWinBmSolarEnergy(SurfNum) = 0.0;
     323           46 :                     s_surf->SurfWinBmBmSolarEnergy(SurfNum) = 0.0;
     324           46 :                     s_surf->SurfWinBmDifSolarEnergy(SurfNum) = 0.0;
     325              : 
     326           46 :                     s_surf->SurfWinHeatGain(SurfNum) = 0.0;
     327           46 :                     s_surf->SurfWinHeatGainRep(SurfNum) = 0.0;
     328           46 :                     s_surf->SurfWinHeatLossRep(SurfNum) = 0.0;
     329              :                 }
     330          190 :                 for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
     331           46 :                     s_surf->SurfWinGainConvGlazToZoneRep(SurfNum) = 0.0;
     332           46 :                     s_surf->SurfWinGainIRGlazToZoneRep(SurfNum) = 0.0;
     333           46 :                     s_surf->SurfWinLossSWZoneToOutWinRep(SurfNum) = 0.0;
     334           46 :                     s_surf->SurfWinGainFrameDividerToZoneRep(SurfNum) = 0.0;
     335           46 :                     s_surf->SurfWinGainConvShadeToZoneRep(SurfNum) = 0.0;
     336           46 :                     s_surf->SurfWinGainIRShadeToZoneRep(SurfNum) = 0.0;
     337           46 :                     s_surf->SurfWinGapConvHtFlowRep(SurfNum) = 0.0;
     338           46 :                     s_surf->SurfWinShadingAbsorbedSolar(SurfNum) = 0.0;
     339              : 
     340           46 :                     s_surf->SurfWinSysSolTransmittance(SurfNum) = 0.0;
     341           46 :                     s_surf->SurfWinSysSolReflectance(SurfNum) = 0.0;
     342           46 :                     s_surf->SurfWinSysSolAbsorptance(SurfNum) = 0.0;
     343              :                 }
     344          190 :                 for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
     345           46 :                     s_surf->SurfWinDifSolarEnergy(SurfNum) = 0.0;
     346           46 :                     s_surf->SurfWinHeatGainRepEnergy(SurfNum) = 0.0;
     347           46 :                     s_surf->SurfWinHeatLossRepEnergy(SurfNum) = 0.0;
     348           46 :                     s_surf->SurfWinGapConvHtFlowRepEnergy(SurfNum) = 0.0;
     349           46 :                     s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfNum) = 0.0;
     350              : 
     351           46 :                     state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfNum) = 0.0;
     352           46 :                     state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfNum) = 0.0;
     353           46 :                     state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfNum) = 0.0;
     354           46 :                     state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfNum) = 0.0;
     355              : 
     356           46 :                     s_surf->SurfWinInsideGlassCondensationFlag(SurfNum) = 0;
     357           46 :                     s_surf->SurfWinInsideFrameCondensationFlag(SurfNum) = 0;
     358           46 :                     s_surf->SurfWinInsideDividerCondensationFlag(SurfNum) = 0;
     359              :                 }
     360          127 :             }
     361              :         }
     362              :     }
     363              : 
     364              :     // Initialize these once
     365          833 :     for (int IPhi = 1; IPhi <= NPhi; ++IPhi) {   // Loop over patch altitude values
     366          714 :         Real64 Phi = PhiMin + (IPhi - 1) * DPhi; // 7.5,22.5,37.5,52.5,67.5,82.5 for NPhi = 6
     367          714 :         state.dataSolarShading->sin_Phi.push_back(std::sin(Phi));
     368          714 :         state.dataSolarShading->cos_Phi.push_back(std::cos(Phi));
     369              :     }
     370              : 
     371         2975 :     for (int ITheta = 1; ITheta <= NTheta; ++ITheta) { // Loop over patch azimuth values
     372         2856 :         Real64 Theta = (ITheta - 1) * DTheta;          // 0,15,30,....,330,345 for NTheta = 24
     373         2856 :         state.dataSolarShading->sin_Theta.push_back(std::sin(Theta));
     374         2856 :         state.dataSolarShading->cos_Theta.push_back(std::cos(Theta));
     375              :     }
     376              : 
     377          119 :     state.dataSolarShading->firstTime = false;
     378          119 : }
     379              : 
     380          112 : void checkShadingSurfaceSchedules(EnergyPlusData &state)
     381              : {
     382          112 :     auto &s_surf = state.dataSurface;
     383              : 
     384              :     // Shading surfaces with a transmittance schedule that is always 1.0 are marked IsTransparent during shading surface input processing
     385              :     // Now that EMS (and other types) actuators are set up, check to see if the schedule has an actuator and reset if needed
     386          158 :     for (int surfNum = s_surf->ShadingSurfaceFirst; surfNum <= s_surf->ShadingSurfaceLast; ++surfNum) {
     387           46 :         auto &thisSurface = s_surf->Surface(surfNum);
     388           46 :         if (!thisSurface.IsTransparent) {
     389           42 :             continue;
     390              :         }
     391              :         // creating some dummy bools here on purpose -- we need to do some renaming and/or consolidate these into a meaningful new global sometime
     392              :         // for now I want the logic to be as readable as possible, so creating shorthand variables makes it very clear
     393            4 :         bool const anyPlugins = size(state.dataPluginManager->plugins) > 0;
     394            4 :         bool const runningByAPI = state.dataGlobal->eplusRunningViaAPI;
     395            4 :         bool const anyEMS = state.dataGlobal->AnyEnergyManagementSystemInModel;
     396            4 :         if ((anyEMS && EMSManager::isScheduleManaged(state, thisSurface.shadowSurfSched)) || runningByAPI || anyPlugins) {
     397              :             // Transmittance schedule definitely has an actuator or may have one via python plugin or API
     398              :             // Set not transparent so it won't be skipped during shading calcs
     399            0 :             thisSurface.IsTransparent = false;
     400              :             // Also set global flags
     401            0 :             state.dataSolarShading->anyScheduledShadingSurface = true;
     402            0 :             s_surf->ShadingTransmittanceVaries = true;
     403            4 :         } else if (!thisSurface.MirroredSurf) {
     404              :             // Warning moved here from shading surface input processing (skip warning for mirrored surfaces)
     405            4 :             ShowWarningError(state,
     406            4 :                              format(R"(Shading Surface="{}", Transmittance Schedule Name="{}", is always transparent.)",
     407            2 :                                     thisSurface.Name,
     408            2 :                                     thisSurface.shadowSurfSched->Name));
     409            6 :             ShowContinueError(state, "This shading surface will be ignored.");
     410              :         }
     411              :     }
     412          112 : }
     413              : 
     414          134 : void GetShadowingInput(EnergyPlusData &state)
     415              : {
     416              :     // SUBROUTINE INFORMATION:
     417              :     //       AUTHOR         Linda K. Lawrie
     418              :     //       DATE WRITTEN   July 1999
     419              :     //       MODIFIED       B. Griffith, Nov 2012, add calculation method
     420              : 
     421              :     // PURPOSE OF THIS SUBROUTINE:
     422              :     // This subroutine gets the Shadowing Calculation object.
     423              : 
     424          134 :     auto &s_surf = state.dataSurface;
     425              : 
     426              :     // Using/Aliasing
     427              :     using DataSystemVariables::ShadingMethod;
     428              : 
     429              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     430              :     int NumItems;
     431              :     int NumNumbers;
     432              :     int NumAlphas;
     433              :     int IOStat;
     434          134 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     435          134 :     state.dataIPShortCut->rNumericArgs({1, 4}) = 0.0; // so if nothing gotten, defaults will be maintained.
     436          134 :     state.dataIPShortCut->cAlphaArgs(1) = "";
     437          134 :     state.dataIPShortCut->cAlphaArgs(2) = "";
     438          134 :     cCurrentModuleObject = "ShadowCalculation";
     439          134 :     NumItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     440          134 :     NumAlphas = 0;
     441          134 :     NumNumbers = 0;
     442          134 :     if (NumItems > 1) {
     443            0 :         ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", cCurrentModuleObject));
     444              :     }
     445              : 
     446          134 :     if (NumItems != 0) {
     447           46 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     448              :                                                                  cCurrentModuleObject,
     449              :                                                                  1,
     450           23 :                                                                  state.dataIPShortCut->cAlphaArgs,
     451              :                                                                  NumAlphas,
     452           23 :                                                                  state.dataIPShortCut->rNumericArgs,
     453              :                                                                  NumNumbers,
     454              :                                                                  IOStat,
     455           23 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     456           23 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     457           23 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     458           23 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     459           23 :         state.dataSolarShading->ShadowingCalcFrequency = state.dataIPShortCut->rNumericArgs(1);
     460              :     }
     461              : 
     462          134 :     if (state.dataSolarShading->ShadowingCalcFrequency <= 0) {
     463              :         //  Set to default value
     464          111 :         state.dataSolarShading->ShadowingCalcFrequency = 20;
     465              :     }
     466          134 :     if (state.dataSolarShading->ShadowingCalcFrequency > 31) {
     467            1 :         ShowWarningError(state, format("{}: suspect {}", cCurrentModuleObject, state.dataIPShortCut->cNumericFieldNames(1)));
     468            1 :         ShowContinueError(state, format("Value entered=[{:.0R}], Shadowing Calculations will be inaccurate.", state.dataIPShortCut->rNumericArgs(1)));
     469              :     }
     470              : 
     471          134 :     if (state.dataIPShortCut->rNumericArgs(2) > 199.0) {
     472           23 :         state.dataSolarShading->MaxHCS = state.dataIPShortCut->rNumericArgs(2);
     473              :     } else {
     474          111 :         state.dataSolarShading->MaxHCS = 15000;
     475              :     }
     476              : 
     477          134 :     int aNum = 1;
     478          134 :     unsigned pixelRes = 512u;
     479          134 :     if (NumAlphas >= aNum) {
     480           23 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Scheduled")) {
     481            0 :             state.dataSysVars->shadingMethod = ShadingMethod::Scheduled;
     482            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Scheduled";
     483            0 :             checkScheduledSurfacePresent(state);
     484           23 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Imported")) {
     485            0 :             if (state.dataSched->ScheduleFileShadingProcessed) {
     486            0 :                 state.dataSysVars->shadingMethod = ShadingMethod::Imported;
     487            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "Imported";
     488              :             } else {
     489            0 :                 ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     490            0 :                 ShowContinueError(state,
     491            0 :                                   format("Value entered=\"{}\" while no Schedule:File:Shading object is defined, InternalCalculation will be used.",
     492            0 :                                          state.dataIPShortCut->cAlphaArgs(aNum)));
     493              :             }
     494           23 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PolygonClipping")) {
     495           19 :             state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     496           19 :             state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     497            4 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PixelCounting")) {
     498            4 :             state.dataSysVars->shadingMethod = ShadingMethod::PixelCounting;
     499            4 :             state.dataIPShortCut->cAlphaArgs(aNum) = "PixelCounting";
     500            4 :             if (NumNumbers >= 3) {
     501            4 :                 pixelRes = (unsigned)state.dataIPShortCut->rNumericArgs(3);
     502              :             }
     503              : #ifdef EP_NO_OPENGL
     504              :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     505              :             ShowContinueError(state, format("Value entered=\"{}\"", state.dataIPShortCut->cAlphaArgs(aNum)));
     506              :             ShowContinueError(state, "This version of EnergyPlus was not compiled to use OpenGL (required for PixelCounting)");
     507              :             ShowContinueError(state, "PolygonClipping will be used instead");
     508              :             state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     509              :             state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     510              : #else
     511            4 :             if (Penumbra::Penumbra::is_valid_context()) {
     512            4 :                 std::shared_ptr<EnergyPlusLogger> penumbra_logger = std::make_shared<EnergyPlusLogger>(EnergyPlusLogger::Log_level::Info);
     513            4 :                 state.dataSolarShading->LoggerContext = std::make_pair<EnergyPlusData *, std::string>(&state, "");
     514            4 :                 penumbra_logger->set_message_context(&state.dataSolarShading->LoggerContext);
     515            4 :                 state.dataSolarShading->penumbra = std::make_unique<Penumbra::Penumbra>(pixelRes, penumbra_logger);
     516            4 :             } else {
     517            0 :                 ShowWarningError(state, "No GPU found (required for PixelCounting)");
     518            0 :                 ShowContinueError(state, "PolygonClipping will be used instead");
     519            0 :                 state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     520            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     521              :             }
     522              : #endif
     523              :         } else {
     524            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     525            0 :             ShowContinueError(state, format("Value entered=\"{}\", PolygonClipping will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     526              :         }
     527              :     } else {
     528          111 :         state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     529          111 :         state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     530              :     }
     531              : 
     532          134 :     aNum++;
     533          134 :     if (NumAlphas >= aNum) {
     534           23 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Periodic")) {
     535           14 :             state.dataSysVars->DetailedSolarTimestepIntegration = false;
     536           14 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
     537            9 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Timestep")) {
     538            9 :             state.dataSysVars->DetailedSolarTimestepIntegration = true;
     539            9 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Timestep";
     540              :         } else {
     541            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     542            0 :             ShowContinueError(state, format("Value entered=\"{}\", Periodic will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     543            0 :             state.dataSysVars->DetailedSolarTimestepIntegration = false;
     544            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
     545              :         }
     546              :     } else {
     547          111 :         state.dataSysVars->DetailedSolarTimestepIntegration = false;
     548          111 :         state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
     549              :     }
     550              : 
     551          134 :     aNum++;
     552          134 :     if (NumAlphas >= aNum) {
     553           13 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SutherlandHodgman")) {
     554            9 :             state.dataSysVars->SutherlandHodgman = true;
     555            9 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
     556            4 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "ConvexWeilerAtherton")) {
     557            2 :             state.dataSysVars->SutherlandHodgman = false;
     558            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
     559            2 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SlaterBarskyandSutherlandHodgman")) {
     560            2 :             state.dataSysVars->SutherlandHodgman = true;
     561            2 :             state.dataSysVars->SlaterBarsky = true;
     562            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
     563            0 :         } else if (state.dataIPShortCut->lAlphaFieldBlanks(aNum)) {
     564            0 :             if (!state.dataSysVars->SutherlandHodgman) { // if already set.
     565            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
     566              :             } else {
     567            0 :                 if (!state.dataSysVars->SlaterBarsky) {
     568            0 :                     state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
     569              :                 } else {
     570            0 :                     state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
     571              :                 }
     572              :             }
     573              :         } else {
     574            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     575            0 :             if (!state.dataSysVars->SutherlandHodgman) {
     576            0 :                 ShowContinueError(state, format("Value entered=\"{}\", ConvexWeilerAtherton will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     577              :             } else {
     578            0 :                 if (!state.dataSysVars->SlaterBarsky) {
     579            0 :                     ShowContinueError(state, format("Value entered=\"{}\", SutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     580              :                 } else {
     581            0 :                     ShowContinueError(
     582              :                         state,
     583            0 :                         format("Value entered=\"{}\", SlaterBarskyandSutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     584              :                 }
     585              :             }
     586              :         }
     587              :     } else {
     588          121 :         if (!state.dataSysVars->SutherlandHodgman) {
     589            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
     590              :         } else {
     591          121 :             if (!state.dataSysVars->SlaterBarsky) {
     592          121 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
     593              :             } else {
     594            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
     595              :             }
     596              :         }
     597              :     }
     598              : 
     599          134 :     aNum++;
     600          134 :     if (NumAlphas >= aNum) {
     601           13 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SimpleSkyDiffuseModeling")) {
     602            5 :             state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
     603            5 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
     604            8 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "DetailedSkyDiffuseModeling")) {
     605            8 :             state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
     606            8 :             state.dataIPShortCut->cAlphaArgs(aNum) = "DetailedSkyDiffuseModeling";
     607            0 :         } else if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     608            0 :             state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
     609            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
     610              :         } else {
     611            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     612            0 :             ShowContinueError(state, format("Value entered=\"{}\", SimpleSkyDiffuseModeling will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     613              :         }
     614              :     } else {
     615          121 :         state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
     616          121 :         state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
     617              :     }
     618              : 
     619          134 :     aNum++;
     620          134 :     if (NumAlphas >= aNum) {
     621            2 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
     622            0 :             state.dataSysVars->ReportExtShadingSunlitFrac = true;
     623            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
     624            2 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
     625            2 :             state.dataSysVars->ReportExtShadingSunlitFrac = false;
     626            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     627              :         } else {
     628            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     629            0 :             ShowContinueError(state, format("Value entered=\"{}\", InternalCalculation will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     630              :         }
     631              :     } else {
     632          132 :         state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     633          132 :         state.dataSysVars->ReportExtShadingSunlitFrac = false;
     634              :     }
     635              : 
     636          134 :     aNum++;
     637          134 :     if (NumAlphas >= aNum) {
     638            2 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
     639            1 :             state.dataSysVars->DisableSelfShadingWithinGroup = true;
     640            1 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
     641            1 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
     642            1 :             state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     643              :         } else {
     644            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     645            0 :             ShowContinueError(state,
     646            0 :                               format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
     647              :         }
     648              :     } else {
     649          132 :         state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     650              :     }
     651              : 
     652          134 :     aNum++;
     653          134 :     if (NumAlphas >= aNum) {
     654            2 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
     655            0 :             state.dataSysVars->DisableSelfShadingBetweenGroup = true;
     656            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
     657            2 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
     658            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     659              :         } else {
     660            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     661            0 :             ShowContinueError(state,
     662            0 :                               format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
     663              :         }
     664              :     } else {
     665          132 :         state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     666              :     }
     667              : 
     668          134 :     if (state.dataSysVars->DisableSelfShadingBetweenGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
     669            0 :         state.dataSysVars->DisableAllSelfShading = true;
     670          134 :     } else if (state.dataSysVars->DisableSelfShadingBetweenGroup || state.dataSysVars->DisableSelfShadingWithinGroup) {
     671            1 :         state.dataSysVars->DisableGroupSelfShading = true;
     672              :     }
     673              : 
     674          134 :     aNum++;
     675          134 :     state.dataSysVars->shadingGroupsNum = NumAlphas - (aNum - 1);
     676          134 :     state.dataSysVars->shadingGroupZoneListNames.allocate(state.dataSysVars->shadingGroupsNum);
     677          135 :     for (int numZone = 1; numZone <= state.dataSysVars->shadingGroupsNum; ++numZone) {
     678            1 :         state.dataSysVars->shadingGroupZoneListNames(numZone) = state.dataIPShortCut->cAlphaArgs(aNum - 1 + numZone);
     679              :     }
     680              : 
     681          134 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration && s_surf->ShadingTransmittanceVaries &&
     682            0 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
     683              : 
     684            0 :         ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
     685            0 :         ShowContinueError(state,
     686            0 :                           format("Choose Shading Calculation Update Frequency Method = Timestep in the {} object to capture all shading impacts.",
     687              :                                  cCurrentModuleObject));
     688              :     }
     689          134 :     if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
     690            0 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
     691              : 
     692            0 :         ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
     693            0 :         ShowContinueError(state, "Simulation has been reset to use DetailedSkyDiffuseModeling. Simulation continues.");
     694            0 :         ShowContinueError(state, format("Choose DetailedSkyDiffuseModeling in the {} object to remove this warning.", cCurrentModuleObject));
     695            0 :         state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
     696            0 :         state.dataIPShortCut->cAlphaArgs(2) = "DetailedSkyDiffuseModeling";
     697            0 :         if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSolarShading->ShadowingCalcFrequency > 1) {
     698            0 :             ShowContinueError(state,
     699            0 :                               format("Better accuracy may be gained by setting the {} to 1 in the {} object.",
     700            0 :                                      state.dataIPShortCut->cNumericFieldNames(1),
     701              :                                      cCurrentModuleObject));
     702              :         }
     703          134 :     } else if (state.dataSysVars->DetailedSkyDiffuseAlgorithm) {
     704            8 :         if (!s_surf->ShadingTransmittanceVaries || state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
     705           16 :             ShowWarningError(state,
     706              :                              "GetShadowingInput: DetailedSkyDiffuseModeling is chosen but not needed as either the shading transmittance for "
     707              :                              "shading devices does not change throughout the year");
     708           16 :             ShowContinueError(state, " or MinimalShadowing has been chosen.");
     709           16 :             ShowContinueError(state, "Simulation should be set to use SimpleSkyDiffuseModeling, but is left at Detailed for simulation.");
     710            8 :             ShowContinueError(state, format("Choose SimpleSkyDiffuseModeling in the {} object to reduce computation time.", cCurrentModuleObject));
     711              :         }
     712              :     }
     713              : 
     714          134 :     print(state.files.eio,
     715              :           "{}",
     716              :           "! <Shadowing/Sun Position Calculations Annual Simulations>, Shading Calculation Method, "
     717              :           "Shading Calculation Update Frequency Method, Shading Calculation Update Frequency {days}, "
     718              :           "Maximum Figures in Shadow Overlap Calculations {}, Polygon Clipping Algorithm, Pixel Counting Resolution, Sky Diffuse Modeling "
     719              :           "Algorithm, Output External Shading Calculation Results, Disable "
     720              :           "Self-Shading Within Shading Zone Groups, Disable Self-Shading From Shading Zone Groups to Other Zones\n");
     721          938 :     print(state.files.eio,
     722              :           "Shadowing/Sun Position Calculations Annual Simulations,{},{},{},{},{},{},{},{},{},{}\n",
     723          134 :           state.dataIPShortCut->cAlphaArgs(1),
     724          134 :           state.dataIPShortCut->cAlphaArgs(2),
     725          134 :           state.dataSolarShading->ShadowingCalcFrequency,
     726          134 :           state.dataSolarShading->MaxHCS,
     727          134 :           state.dataIPShortCut->cAlphaArgs(3),
     728              :           pixelRes,
     729          134 :           state.dataIPShortCut->cAlphaArgs(4),
     730          134 :           state.dataIPShortCut->cAlphaArgs(5),
     731          134 :           state.dataIPShortCut->cAlphaArgs(6),
     732          134 :           state.dataIPShortCut->cAlphaArgs(7));
     733          134 : }
     734              : 
     735          114 : void processShadowingInput(EnergyPlusData &state)
     736              : {
     737              :     // all shadow input processing that needed zones and surfaces to already be read into data (part of fix for Defect #10299)
     738              : 
     739          115 :     if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) &&
     740            1 :         state.dataSolarShading->anyScheduledShadingSurface) {
     741            2 :         ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; ");
     742            2 :         ShowContinueError(state, "and there is at least one shading surface of type ");
     743            2 :         ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, ");
     744            2 :         ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary.");
     745            2 :         ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as ");
     746            2 :         ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, ");
     747            2 :         ShowContinueError(state, "which may result in inaccurate or unexpected results.");
     748            3 :         ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\".");
     749              :     }
     750              : 
     751          114 :     if (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::Imported) {
     752            0 :         for (auto &surf : state.dataSurface->Surface) {
     753            0 :             if ((surf.surfExternalShadingSched = Sched::GetSchedule(state, surf.Name + "_shading")) != nullptr) {
     754            0 :                 surf.SurfSchedExternalShadingFrac = true;
     755              :             } else {
     756            0 :                 ShowWarningError(state,
     757            0 :                                  format("processShadowingInput: sunlit fraction schedule not found for {} when using ImportedShading.", surf.Name));
     758            0 :                 ShowContinueError(state, "These values are set to 1.0.");
     759              :             }
     760            0 :         }
     761              :     }
     762              : 
     763              :     int SurfZoneGroup, CurZoneGroup;
     764          114 :     int Found = 0;
     765          114 :     if (state.dataSysVars->DisableGroupSelfShading) {
     766            1 :         Array1D_int DisableSelfShadingGroups;
     767            1 :         int NumOfShadingGroups = state.dataSysVars->shadingGroupsNum;
     768            1 :         if (NumOfShadingGroups > 0) {
     769            1 :             DisableSelfShadingGroups.allocate(NumOfShadingGroups);
     770            2 :             for (int i = 1; i <= NumOfShadingGroups; i++) {
     771            1 :                 Found = Util::FindItemInList(
     772            1 :                     state.dataSysVars->shadingGroupZoneListNames(i), state.dataHeatBal->ZoneList, state.dataHeatBal->NumOfZoneLists);
     773            1 :                 if (Found != 0) {
     774            1 :                     DisableSelfShadingGroups(i) = Found;
     775              :                 }
     776              :             }
     777              : 
     778           10 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
     779            9 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces
     780            9 :                     SurfZoneGroup = 0;
     781              :                     // Check the shading zone group of each exterior surface
     782           18 :                     for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
     783            9 :                         CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
     784           11 :                         for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
     785              :                              ZoneNum++) { // Loop through all zones in the zone list
     786            9 :                             if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) {
     787            7 :                                 SurfZoneGroup = CurZoneGroup;
     788            7 :                                 break;
     789              :                             }
     790              :                         }
     791              :                     }
     792              :                     // if a surface is not in any zone group, no self shading is disabled for this surface
     793            9 :                     if (SurfZoneGroup != 0) {
     794              :                         // if DisableSelfShadingWithinGroup, add all zones in the same zone group to the surface's disabled zone list
     795              :                         // if DisableSelfShadingBetweenGroups, add all zones in all other zone groups to the surface's disabled zone list
     796           14 :                         for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
     797            7 :                             CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
     798            7 :                             if (SurfZoneGroup == CurZoneGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
     799           14 :                                 for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
     800              :                                      ZoneNum++) { // Loop through all zones in the zone list
     801            7 :                                     state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
     802            7 :                                         state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
     803              :                                 }
     804            0 :                             } else if (SurfZoneGroup != CurZoneGroup && state.dataSysVars->DisableSelfShadingBetweenGroup) {
     805            0 :                                 for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; ZoneNum++) {
     806            0 :                                     state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
     807            0 :                                         state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
     808              :                                 }
     809              :                             }
     810              :                         }
     811              :                     }
     812              :                 }
     813              :             }
     814              :         } else {
     815            0 :             ShowFatalError(state, "No Shading groups are defined when disabling grouped self shading.");
     816              :         }
     817            1 :     }
     818          114 : }
     819              : 
     820            1 : void checkScheduledSurfacePresent(EnergyPlusData &state)
     821              : {
     822              :     // User has chosen "Scheduled" for sunlit fraction so check to see which surfaces don't have a schedule
     823            1 :     int numNotDef = 0;
     824            1 :     int constexpr maxErrMessages = 50;
     825            1 :     auto &surfData = state.dataSurface;
     826            6 :     for (int surfNum = 1; surfNum <= surfData->TotSurfaces; ++surfNum) {
     827            5 :         auto &thisSurf = surfData->Surface(surfNum);
     828            5 :         if ((thisSurf.Class == SurfaceClass::Shading || thisSurf.Class == SurfaceClass::Detached_F || thisSurf.Class == SurfaceClass::Detached_B ||
     829            4 :              thisSurf.Class == SurfaceClass::Overhang || thisSurf.Class == SurfaceClass::Fin)) {
     830            2 :             continue; // skip shading surfaces
     831              :         }
     832            3 :         if (!thisSurf.SurfSchedExternalShadingFrac) {
     833            1 :             numNotDef += 1;
     834            1 :             if (numNotDef == 1) {
     835            2 :                 ShowWarningError(
     836              :                     state,
     837            2 :                     format("ShadowCalculation specified Schedule for the Shading Calculation Method but no schedule provided for {}", thisSurf.Name));
     838            2 :                 ShowContinueError(
     839              :                     state, "When Schedule is selected for the Shading Calculation Method and no schedule is provided for a particular surface,");
     840            2 :                 ShowContinueError(
     841              :                     state, "EnergyPlus will assume that the surface is not shaded.  Use SurfaceProperty:LocalEnvironment to specify a schedule");
     842            3 :                 ShowContinueError(state, "for sunlit fraction if this was not desired.  Otherwise, this surface will not be shaded at all.");
     843            0 :             } else if (numNotDef <= maxErrMessages) {
     844            0 :                 ShowWarningError(state, format("No schedule was provided for {} either.  See above error message for more details", thisSurf.Name));
     845              :             }
     846              :         }
     847              :     }
     848            1 :     if (numNotDef > maxErrMessages) {
     849            0 :         ShowContinueError(state, format("This message is only shown for the first {} occurrences of this issue.", maxErrMessages));
     850              :     }
     851            1 : }
     852              : 
     853          141 : void AllocateModuleArrays(EnergyPlusData &state)
     854              : {
     855              : 
     856              :     // SUBROUTINE INFORMATION:
     857              :     //       AUTHOR         Rick Strand
     858              :     //       DATE WRITTEN   February 1998
     859              :     //       MODIFIED       August 2005 JG - Added output variables for energy in J
     860              : 
     861              :     // PURPOSE OF THIS SUBROUTINE:
     862              :     // This routine allocates all of the arrays at the module level which
     863              :     // require allocation.
     864              : 
     865              :     // METHODOLOGY EMPLOYED:
     866              :     // Allocation is dependent on the user input file.
     867              : 
     868              :     int I;
     869              :     int NumOfLayers;
     870              : 
     871          141 :     auto &s_surf = state.dataSurface;
     872              : 
     873          141 :     state.dataSolarShading->SurfSunCosTheta.dimension(s_surf->TotSurfaces, 0.0);
     874          141 :     state.dataSolarShading->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
     875          141 :     if (!state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() || !state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
     876          141 :         state.dataSolarShading->SurfWinIntBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
     877          141 :         state.dataSolarShading->SurfWinExtBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
     878          141 :         state.dataSolarShading->SurfWinTransBmSolar.allocate(s_surf->TotSurfaces);
     879          141 :         state.dataSolarShading->SurfWinTransDifSolar.allocate(s_surf->TotSurfaces);
     880          141 :         state.dataSolarShading->SurfWinTransDifSolarGnd.allocate(s_surf->TotSurfaces);
     881          141 :         state.dataSolarShading->SurfWinTransDifSolarSky.allocate(s_surf->TotSurfaces);
     882          141 :         state.dataSolarShading->SurfWinTransBmBmSolar.allocate(s_surf->TotSurfaces);
     883          141 :         state.dataSolarShading->SurfWinTransBmDifSolar.allocate(s_surf->TotSurfaces);
     884              :     }
     885          141 :     state.dataSolarShading->SurfAnisoSkyMult.dimension(s_surf->TotSurfaces, 1.0);
     886          141 :     state.dataSolarShading->SurfIntAbsFac.dimension(s_surf->TotSurfaces, 0.0);
     887              :     // For isotropic sky: recalculated in AnisoSkyViewFactors if anisotropic radiance
     888              :     //  ALLOCATE(WithShdgIsoSky(TotSurfaces))
     889              :     //  WithShdgIsoSky=0.0
     890              :     //  ALLOCATE(WoShdgIsoSky(TotSurfaces))
     891              :     //  WoShdgIsoSky=0.0
     892              :     //  ALLOCATE(WithShdgHoriz(TotSurfaces))
     893              :     //  WithShdgHoriz=0.0
     894              :     //  ALLOCATE(WoShdgHoriz(TotSurfaces))
     895              :     //  WoShdgHoriz=0.0
     896              :     //  ALLOCATE(DifShdgRatioIsoSky(TotSurfaces))
     897              :     //  DifShdgRatioIsoSky=0.0
     898              :     //  ALLOCATE(DifShdgRatioHoriz(TotSurfaces))
     899              :     //  DifShdgRatioHoriz=0.0
     900          141 :     state.dataSolarShading->SurfMultIsoSky.dimension(s_surf->TotSurfaces, 0.0);
     901          141 :     state.dataSolarShading->SurfMultCircumSolar.dimension(s_surf->TotSurfaces, 0.0);
     902          141 :     state.dataSolarShading->SurfMultHorizonZenith.dimension(s_surf->TotSurfaces, 0.0);
     903          141 :     state.dataSolarShading->SurfWinRevealStatus.dimension(24, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0);
     904              : 
     905              :     // Weiler-Atherton
     906          141 :     state.dataSolarShading->MAXHCArrayBounds = 2 * (s_surf->MaxVerticesPerSurface + 1);
     907          141 :     state.dataSolarShading->MAXHCArrayIncrement = s_surf->MaxVerticesPerSurface + 1;
     908          141 :     state.dataSolarShading->XTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     909          141 :     state.dataSolarShading->YTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     910          141 :     state.dataSolarShading->XVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     911          141 :     state.dataSolarShading->XVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     912          141 :     state.dataSolarShading->YVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     913          141 :     state.dataSolarShading->YVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     914          141 :     state.dataSolarShading->ZVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     915              : 
     916              :     // Sutherland-Hodgman
     917          141 :     state.dataSolarShading->ATEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     918          141 :     state.dataSolarShading->BTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     919          141 :     state.dataSolarShading->CTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     920          141 :     state.dataSolarShading->XTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     921          141 :     state.dataSolarShading->YTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     922              : 
     923          141 :     s_surf->SurfSunCosHourly.allocate(Constant::iHoursInDay);
     924         3525 :     for (int hour = 1; hour <= Constant::iHoursInDay; hour++) {
     925         3384 :         s_surf->SurfSunCosHourly(hour) = 0.0;
     926              :     }
     927          141 :     s_surf->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
     928          141 :     s_surf->SurfSunlitFrac.dimension(s_surf->TotSurfaces, 0.0);
     929          141 :     s_surf->SurfSkySolarInc.dimension(s_surf->TotSurfaces, 0);
     930          141 :     s_surf->SurfGndSolarInc.dimension(s_surf->TotSurfaces, 0);
     931          141 :     s_surf->SurfBmToBmReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
     932          141 :     s_surf->SurfBmToDiffReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
     933          141 :     s_surf->SurfBmToDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
     934          141 :     s_surf->SurfSkyDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
     935          141 :     s_surf->SurfOpaqAI.dimension(s_surf->TotSurfaces, 0.0);
     936          141 :     s_surf->SurfOpaqAO.dimension(s_surf->TotSurfaces, 0.0);
     937          141 :     s_surf->SurfWinTransSolar.dimension(s_surf->TotSurfaces, 0.0);
     938          141 :     s_surf->SurfWinBmSolar.dimension(s_surf->TotSurfaces, 0.0);
     939          141 :     s_surf->SurfWinBmBmSolar.dimension(s_surf->TotSurfaces, 0.0);
     940          141 :     s_surf->SurfWinBmDifSolar.dimension(s_surf->TotSurfaces, 0.0);
     941          141 :     s_surf->SurfWinDifSolar.dimension(s_surf->TotSurfaces, 0.0);
     942          141 :     s_surf->SurfWinHeatGain.dimension(s_surf->TotSurfaces, 0.0);
     943          141 :     s_surf->SurfWinHeatGainRep.dimension(s_surf->TotSurfaces, 0.0);
     944          141 :     s_surf->SurfWinHeatLossRep.dimension(s_surf->TotSurfaces, 0.0);
     945          141 :     s_surf->SurfWinGainConvGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     946          141 :     s_surf->SurfWinGainIRGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     947          141 :     s_surf->SurfWinLossSWZoneToOutWinRep.dimension(s_surf->TotSurfaces, 0.0);
     948          141 :     s_surf->SurfWinGainFrameDividerToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     949          141 :     s_surf->SurfWinGainConvShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     950          141 :     s_surf->SurfWinGainIRShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     951          141 :     s_surf->SurfWinGapConvHtFlowRep.dimension(s_surf->TotSurfaces, 0.0);
     952          141 :     s_surf->SurfWinShadingAbsorbedSolar.dimension(s_surf->TotSurfaces, 0.0);
     953          141 :     s_surf->SurfWinSysSolTransmittance.dimension(s_surf->TotSurfaces, 0.0);
     954          141 :     s_surf->SurfWinSysSolReflectance.dimension(s_surf->TotSurfaces, 0.0);
     955          141 :     s_surf->SurfWinSysSolAbsorptance.dimension(s_surf->TotSurfaces, 0.0);
     956          141 :     s_surf->SurfWinInsideGlassCondensationFlag.dimension(s_surf->TotSurfaces, 0);
     957          141 :     s_surf->SurfWinInsideFrameCondensationFlag.dimension(s_surf->TotSurfaces, 0);
     958          141 :     s_surf->SurfWinInsideDividerCondensationFlag.dimension(s_surf->TotSurfaces, 0);
     959              : 
     960          141 :     state.dataHeatBal->SurfSunlitFracHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
     961          141 :     state.dataHeatBal->SurfSunlitFrac.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
     962          141 :     state.dataHeatBal->SurfSunlitFracWithoutReveal.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
     963          564 :     state.dataHeatBal->SurfWinBackSurfaces.dimension(
     964          423 :         Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0);
     965          564 :     state.dataHeatBal->SurfWinOverlapAreas.dimension(
     966          423 :         Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0.0);
     967          141 :     state.dataHeatBal->SurfCosIncAngHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
     968          141 :     state.dataHeatBal->SurfCosIncAng.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
     969              : 
     970          141 :     state.dataHeatBal->ZoneTransSolar.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     971          141 :     state.dataHeatBal->ZoneBmSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     972          141 :     state.dataHeatBal->ZoneBmSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     973          141 :     state.dataHeatBal->EnclSolInitialDifSolReflW.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     974          141 :     state.dataHeatBal->ZoneDifSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     975          141 :     state.dataHeatBal->ZoneDifSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     976          141 :     state.dataHeatBal->ZoneWinHeatGain.dimension(state.dataGlobal->NumOfZones, 0.0);
     977          141 :     state.dataHeatBal->ZoneWinHeatGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     978          141 :     state.dataHeatBal->ZoneWinHeatLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     979          141 :     state.dataHeatBal->ZoneOpaqSurfInsFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
     980          141 :     state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     981          141 :     state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     982          141 :     state.dataHeatBal->ZoneOpaqSurfExtFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
     983          141 :     state.dataHeatBal->ZoneOpaqSurfExtFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     984          141 :     state.dataHeatBal->ZoneOpaqSurfExtFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     985              : 
     986          141 :     state.dataHeatBal->SurfQRadSWOutIncident.dimension(s_surf->TotSurfaces, 0.0);
     987          141 :     state.dataHeatBal->SurfQRadSWOutIncidentBeam.dimension(s_surf->TotSurfaces, 0.0);
     988          141 :     state.dataHeatBal->SurfBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
     989          141 :     state.dataHeatBal->SurfBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
     990              :     //  ALLOCATE(DifIncInsSurfIntensRep(TotSurfaces))
     991              :     //  DifIncInsSurfIntensRep=0.0
     992              :     //  ALLOCATE(DifIncInsSurfAmountRep(TotSurfaces))
     993              :     //  DifIncInsSurfAmountRep=0.0
     994          141 :     state.dataHeatBal->SurfIntBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
     995          141 :     state.dataHeatBal->SurfIntBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
     996              :     //  ALLOCATE(IntDifIncInsSurfIntensRep(TotSurfaces))
     997              :     //  IntDifIncInsSurfIntensRep=0.0
     998              :     //  ALLOCATE(IntDifIncInsSurfAmountRep(TotSurfaces))
     999              :     //  IntDifIncInsSurfAmountRep=0.0
    1000          141 :     state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse.dimension(s_surf->TotSurfaces, 0.0);
    1001          141 :     state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse.dimension(s_surf->TotSurfaces, 0.0);
    1002          141 :     state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
    1003          141 :     state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
    1004          141 :     state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs.dimension(s_surf->TotSurfaces, 0.0);
    1005          141 :     state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
    1006          141 :     state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
    1007          141 :     state.dataHeatBal->SurfCosIncidenceAngle.dimension(s_surf->TotSurfaces, 0.0);
    1008              : 
    1009          141 :     state.dataHeatBal->SurfWinBSDFBeamDirectionRep.dimension(s_surf->TotSurfaces, 0);
    1010          141 :     state.dataHeatBal->SurfWinBSDFBeamThetaRep.dimension(s_surf->TotSurfaces, 0.0);
    1011          141 :     state.dataHeatBal->SurfWinBSDFBeamPhiRep.dimension(s_surf->TotSurfaces, 0.0);
    1012          141 :     state.dataHeatBal->SurfWinQRadSWwinAbsTot.dimension(s_surf->TotSurfaces, 0.0);
    1013          141 :     state.dataHeatBal->SurfWinQRadSWwinAbsLayer.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
    1014          141 :     state.dataHeatBal->SurfWinFenLaySurfTempFront.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
    1015          141 :     state.dataHeatBal->SurfWinFenLaySurfTempBack.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
    1016              : 
    1017          141 :     state.dataHeatBal->SurfWinSWwinAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
    1018          141 :     state.dataHeatBal->SurfInitialDifSolInAbsReport.dimension(s_surf->TotSurfaces, 0.0);
    1019          141 :     state.dataHeatBal->SurfWinInitialDifSolInTransReport.dimension(s_surf->TotSurfaces, 0.0);
    1020          141 :     state.dataHeatBal->SurfSWInAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
    1021              : 
    1022              :     // energy
    1023          141 :     s_surf->SurfWinTransSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1024          141 :     s_surf->SurfWinBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1025          141 :     s_surf->SurfWinBmBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1026          141 :     s_surf->SurfWinBmDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1027              : 
    1028          141 :     s_surf->SurfWinDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1029          141 :     s_surf->SurfWinHeatGainRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1030          141 :     s_surf->SurfWinHeatLossRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1031          141 :     s_surf->SurfWinGapConvHtFlowRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1032          141 :     s_surf->SurfWinHeatTransferRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1033          141 :     s_surf->SurfWinShadingAbsorbedSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1034              : 
    1035          141 :     state.dataHeatBal->ZoneTransSolarEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1036          141 :     state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1037          141 :     state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1038          141 :     state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1039          141 :     state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1040          141 :     state.dataHeatBal->ZoneWinHeatGainRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
    1041          141 :     state.dataHeatBal->ZoneWinHeatLossRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
    1042              : 
    1043          141 :     state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1044          141 :     state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1045          141 :     state.dataHeatBal->ZnOpqSurfExtFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1046          141 :     state.dataHeatBal->ZnOpqSurfExtFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1047              :     //  ALLOCATE(DifIncInsSurfAmountRepEnergy(TotSurfaces))
    1048              :     //  DifIncInsSurfAmountRepEnergy=0.0
    1049          141 :     state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1050          141 :     state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1051              :     //  ALLOCATE(IntDifIncInsSurfAmountRepEnergy(TotSurfaces))
    1052              :     //  IntDifIncInsSurfAmountRepEnergy=0.0
    1053          141 :     state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1054              : 
    1055         1151 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
    1056         1010 :         s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
    1057         1010 :         s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
    1058         1010 :         s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
    1059         1010 :         s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
    1060         1010 :         s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
    1061         1010 :         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
    1062         1010 :         s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
    1063         1010 :         s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
    1064         1010 :         s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
    1065         1010 :         s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
    1066              :     }
    1067              : 
    1068              :     // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
    1069         1151 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
    1070         1010 :         s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
    1071         1010 :         s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
    1072         1010 :         s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
    1073         1010 :         s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
    1074              :     }
    1075              : 
    1076          141 :     DisplayString(state, "Initializing Zone and Enclosure Report Variables");
    1077          308 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    1078          167 :         std::string &thisEnclosureName = state.dataViewFactor->EnclSolInfo(enclosureNum).Name;
    1079          334 :         SetupOutputVariable(state,
    1080              :                             "Enclosure Windows Total Transmitted Solar Radiation Rate",
    1081              :                             Constant::Units::W,
    1082          167 :                             state.dataHeatBal->ZoneTransSolar(enclosureNum),
    1083              :                             OutputProcessor::TimeStepType::Zone,
    1084              :                             OutputProcessor::StoreType::Average,
    1085              :                             thisEnclosureName);
    1086          334 :         SetupOutputVariable(state,
    1087              :                             "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Rate",
    1088              :                             Constant::Units::W,
    1089          167 :                             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum),
    1090              :                             OutputProcessor::TimeStepType::Zone,
    1091              :                             OutputProcessor::StoreType::Average,
    1092              :                             thisEnclosureName);
    1093          334 :         SetupOutputVariable(state,
    1094              :                             "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Rate",
    1095              :                             Constant::Units::W,
    1096          167 :                             state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum),
    1097              :                             OutputProcessor::TimeStepType::Zone,
    1098              :                             OutputProcessor::StoreType::Average,
    1099              :                             thisEnclosureName);
    1100          334 :         SetupOutputVariable(state,
    1101              :                             "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Rate",
    1102              :                             Constant::Units::W,
    1103          167 :                             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum),
    1104              :                             OutputProcessor::TimeStepType::Zone,
    1105              :                             OutputProcessor::StoreType::Average,
    1106              :                             thisEnclosureName);
    1107          334 :         SetupOutputVariable(state,
    1108              :                             "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Rate",
    1109              :                             Constant::Units::W,
    1110          167 :                             state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclosureNum),
    1111              :                             OutputProcessor::TimeStepType::Zone,
    1112              :                             OutputProcessor::StoreType::Average,
    1113              :                             thisEnclosureName);
    1114              :         // Energy variables
    1115          334 :         SetupOutputVariable(state,
    1116              :                             "Enclosure Windows Total Transmitted Solar Radiation Energy",
    1117              :                             Constant::Units::J,
    1118          167 :                             state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum),
    1119              :                             OutputProcessor::TimeStepType::Zone,
    1120              :                             OutputProcessor::StoreType::Sum,
    1121              :                             thisEnclosureName);
    1122          334 :         SetupOutputVariable(state,
    1123              :                             "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Energy",
    1124              :                             Constant::Units::J,
    1125          167 :                             state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum),
    1126              :                             OutputProcessor::TimeStepType::Zone,
    1127              :                             OutputProcessor::StoreType::Sum,
    1128              :                             thisEnclosureName);
    1129          334 :         SetupOutputVariable(state,
    1130              :                             "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Energy",
    1131              :                             Constant::Units::J,
    1132          167 :                             state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum),
    1133              :                             OutputProcessor::TimeStepType::Zone,
    1134              :                             OutputProcessor::StoreType::Sum,
    1135              :                             thisEnclosureName);
    1136          334 :         SetupOutputVariable(state,
    1137              :                             "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Energy",
    1138              :                             Constant::Units::J,
    1139          167 :                             state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum),
    1140              :                             OutputProcessor::TimeStepType::Zone,
    1141              :                             OutputProcessor::StoreType::Sum,
    1142              :                             thisEnclosureName);
    1143          334 :         SetupOutputVariable(state,
    1144              :                             "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Energy",
    1145              :                             Constant::Units::J,
    1146          167 :                             state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclosureNum),
    1147              :                             OutputProcessor::TimeStepType::Zone,
    1148              :                             OutputProcessor::StoreType::Sum,
    1149              :                             thisEnclosureName);
    1150              :     }
    1151          300 :     for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
    1152          318 :         SetupOutputVariable(state,
    1153              :                             "Zone Windows Total Heat Gain Rate",
    1154              :                             Constant::Units::W,
    1155          159 :                             state.dataHeatBal->ZoneWinHeatGainRep(ZoneLoop),
    1156              :                             OutputProcessor::TimeStepType::Zone,
    1157              :                             OutputProcessor::StoreType::Average,
    1158          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1159          318 :         SetupOutputVariable(state,
    1160              :                             "Zone Windows Total Heat Loss Rate",
    1161              :                             Constant::Units::W,
    1162          159 :                             state.dataHeatBal->ZoneWinHeatLossRep(ZoneLoop),
    1163              :                             OutputProcessor::TimeStepType::Zone,
    1164              :                             OutputProcessor::StoreType::Average,
    1165          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1166          318 :         SetupOutputVariable(state,
    1167              :                             "Zone Windows Total Heat Gain Energy",
    1168              :                             Constant::Units::J,
    1169          159 :                             state.dataHeatBal->ZoneWinHeatGainRepEnergy(ZoneLoop),
    1170              :                             OutputProcessor::TimeStepType::Zone,
    1171              :                             OutputProcessor::StoreType::Sum,
    1172          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1173          318 :         SetupOutputVariable(state,
    1174              :                             "Zone Windows Total Heat Loss Energy",
    1175              :                             Constant::Units::J,
    1176          159 :                             state.dataHeatBal->ZoneWinHeatLossRepEnergy(ZoneLoop),
    1177              :                             OutputProcessor::TimeStepType::Zone,
    1178              :                             OutputProcessor::StoreType::Sum,
    1179          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1180          159 :         if (state.dataGlobal->DisplayAdvancedReportVariables) {
    1181              :             // CurrentModuleObject='Zone(Advanced)'
    1182            0 :             SetupOutputVariable(state,
    1183              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Rate",
    1184              :                                 Constant::Units::W,
    1185            0 :                                 state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(ZoneLoop),
    1186              :                                 OutputProcessor::TimeStepType::Zone,
    1187              :                                 OutputProcessor::StoreType::Average,
    1188            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1189            0 :             SetupOutputVariable(state,
    1190              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Rate",
    1191              :                                 Constant::Units::W,
    1192            0 :                                 state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(ZoneLoop),
    1193              :                                 OutputProcessor::TimeStepType::Zone,
    1194              :                                 OutputProcessor::StoreType::Average,
    1195            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1196              :             // Energy variables
    1197            0 :             SetupOutputVariable(state,
    1198              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Energy",
    1199              :                                 Constant::Units::J,
    1200            0 :                                 state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(ZoneLoop),
    1201              :                                 OutputProcessor::TimeStepType::Zone,
    1202              :                                 OutputProcessor::StoreType::Sum,
    1203            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1204            0 :             SetupOutputVariable(state,
    1205              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Energy",
    1206              :                                 Constant::Units::J,
    1207            0 :                                 state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(ZoneLoop),
    1208              :                                 OutputProcessor::TimeStepType::Zone,
    1209              :                                 OutputProcessor::StoreType::Sum,
    1210            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1211              :         }
    1212              :     }
    1213              : 
    1214          141 :     DisplayString(state, "Initializing Surface (Shading) Report Variables");
    1215              :     // CurrentModuleObject='Surfaces'
    1216         1151 :     for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
    1217         1010 :         auto &surf = s_surf->Surface(SurfLoop);
    1218         2020 :         SetupOutputVariable(state,
    1219              :                             "Surface Outside Normal Azimuth Angle",
    1220              :                             Constant::Units::deg,
    1221         1010 :                             surf.Azimuth,
    1222              :                             OutputProcessor::TimeStepType::Zone,
    1223              :                             OutputProcessor::StoreType::Average,
    1224         1010 :                             surf.Name);
    1225         1010 :         if (surf.ExtSolar) {
    1226         1388 :             SetupOutputVariable(state,
    1227              :                                 "Surface Outside Face Sunlit Area",
    1228              :                                 Constant::Units::m2,
    1229          694 :                                 s_surf->SurfSunlitArea(SurfLoop),
    1230              :                                 OutputProcessor::TimeStepType::Zone,
    1231              :                                 OutputProcessor::StoreType::Average,
    1232          694 :                                 surf.Name);
    1233         1388 :             SetupOutputVariable(state,
    1234              :                                 "Surface Outside Face Sunlit Fraction",
    1235              :                                 Constant::Units::None,
    1236          694 :                                 s_surf->SurfSunlitFrac(SurfLoop),
    1237              :                                 OutputProcessor::TimeStepType::Zone,
    1238              :                                 OutputProcessor::StoreType::Average,
    1239          694 :                                 surf.Name);
    1240         1388 :             SetupOutputVariable(state,
    1241              :                                 "Surface Outside Face Incident Solar Radiation Rate per Area",
    1242              :                                 Constant::Units::W_m2,
    1243          694 :                                 state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
    1244              :                                 OutputProcessor::TimeStepType::Zone,
    1245              :                                 OutputProcessor::StoreType::Average,
    1246          694 :                                 surf.Name);
    1247         1388 :             SetupOutputVariable(state,
    1248              :                                 "Surface Outside Face Incident Beam Solar Radiation Rate per Area",
    1249              :                                 Constant::Units::W_m2,
    1250          694 :                                 state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfLoop),
    1251              :                                 OutputProcessor::TimeStepType::Zone,
    1252              :                                 OutputProcessor::StoreType::Average,
    1253          694 :                                 surf.Name);
    1254         1388 :             SetupOutputVariable(state,
    1255              :                                 "Surface Outside Face Incident Sky Diffuse Solar Radiation Rate per Area",
    1256              :                                 Constant::Units::W_m2,
    1257          694 :                                 state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfLoop),
    1258              :                                 OutputProcessor::TimeStepType::Zone,
    1259              :                                 OutputProcessor::StoreType::Average,
    1260          694 :                                 surf.Name);
    1261         1388 :             SetupOutputVariable(state,
    1262              :                                 "Surface Outside Face Incident Ground Diffuse Solar Radiation Rate per Area",
    1263              :                                 Constant::Units::W_m2,
    1264          694 :                                 state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfLoop),
    1265              :                                 OutputProcessor::TimeStepType::Zone,
    1266              :                                 OutputProcessor::StoreType::Average,
    1267          694 :                                 surf.Name);
    1268         1388 :             SetupOutputVariable(state,
    1269              :                                 "Surface Outside Face Beam Solar Incident Angle Cosine Value",
    1270              :                                 Constant::Units::None,
    1271          694 :                                 state.dataHeatBal->SurfCosIncidenceAngle(SurfLoop),
    1272              :                                 OutputProcessor::TimeStepType::Zone,
    1273              :                                 OutputProcessor::StoreType::Average,
    1274          694 :                                 surf.Name);
    1275         1388 :             SetupOutputVariable(state,
    1276              :                                 "Surface Outside Face Incident Sky Diffuse Ground Reflected Solar Radiation Rate per Area",
    1277              :                                 Constant::Units::W_m2,
    1278          694 :                                 state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfLoop),
    1279              :                                 OutputProcessor::TimeStepType::Zone,
    1280              :                                 OutputProcessor::StoreType::Average,
    1281          694 :                                 surf.Name);
    1282         1388 :             SetupOutputVariable(state,
    1283              :                                 "Surface Outside Face Incident Sky Diffuse Surface Reflected Solar Radiation Rate per Area",
    1284              :                                 Constant::Units::W_m2,
    1285          694 :                                 state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfLoop),
    1286              :                                 OutputProcessor::TimeStepType::Zone,
    1287              :                                 OutputProcessor::StoreType::Average,
    1288          694 :                                 surf.Name);
    1289         1388 :             SetupOutputVariable(state,
    1290              :                                 "Surface Outside Face Incident Beam To Beam Surface Reflected Solar Radiation Rate per Area",
    1291              :                                 Constant::Units::W_m2,
    1292          694 :                                 state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfLoop),
    1293              :                                 OutputProcessor::TimeStepType::Zone,
    1294              :                                 OutputProcessor::StoreType::Average,
    1295          694 :                                 surf.Name);
    1296         1388 :             SetupOutputVariable(state,
    1297              :                                 "Surface Outside Face Incident Beam To Diffuse Surface Reflected Solar Radiation Rate per Area",
    1298              :                                 Constant::Units::W_m2,
    1299          694 :                                 state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfLoop),
    1300              :                                 OutputProcessor::TimeStepType::Zone,
    1301              :                                 OutputProcessor::StoreType::Average,
    1302          694 :                                 surf.Name);
    1303         1388 :             SetupOutputVariable(state,
    1304              :                                 "Surface Outside Face Incident Beam To Diffuse Ground Reflected Solar Radiation Rate per Area",
    1305              :                                 Constant::Units::W_m2,
    1306          694 :                                 state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfLoop),
    1307              :                                 OutputProcessor::TimeStepType::Zone,
    1308              :                                 OutputProcessor::StoreType::Average,
    1309          694 :                                 surf.Name);
    1310         1388 :             SetupOutputVariable(state,
    1311              :                                 "Surface Anisotropic Sky Multiplier",
    1312              :                                 Constant::Units::None,
    1313          694 :                                 state.dataSolarShading->SurfAnisoSkyMult(SurfLoop),
    1314              :                                 OutputProcessor::TimeStepType::Zone,
    1315              :                                 OutputProcessor::StoreType::Average,
    1316          694 :                                 surf.Name);
    1317          694 :             SetupOutputVariable(state,
    1318              :                                 "Surface Window BSDF Beam Direction Number",
    1319              :                                 Constant::Units::None,
    1320          694 :                                 state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfLoop),
    1321              :                                 OutputProcessor::TimeStepType::Zone,
    1322              :                                 OutputProcessor::StoreType::Average,
    1323          694 :                                 surf.Name);
    1324         1388 :             SetupOutputVariable(state,
    1325              :                                 "Surface Window BSDF Beam Theta Angle",
    1326              :                                 Constant::Units::rad,
    1327          694 :                                 state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfLoop),
    1328              :                                 OutputProcessor::TimeStepType::Zone,
    1329              :                                 OutputProcessor::StoreType::Average,
    1330          694 :                                 surf.Name);
    1331         1388 :             SetupOutputVariable(state,
    1332              :                                 "Surface Window BSDF Beam Phi Angle",
    1333              :                                 Constant::Units::rad,
    1334          694 :                                 state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfLoop),
    1335              :                                 OutputProcessor::TimeStepType::Zone,
    1336              :                                 OutputProcessor::StoreType::Average,
    1337          694 :                                 surf.Name);
    1338              :         }
    1339         1010 :         if (!surf.HeatTransSurf) {
    1340           70 :             continue;
    1341              :         }
    1342              : 
    1343          940 :         if (surf.Class == SurfaceClass::Window) {
    1344              :             // CurrentModuleObject='Windows/GlassDoors'
    1345           73 :             if (surf.ExtSolar) {
    1346          142 :                 SetupOutputVariable(state,
    1347              :                                     "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    1348              :                                     Constant::Units::W,
    1349           71 :                                     state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    1350              :                                     OutputProcessor::TimeStepType::Zone,
    1351              :                                     OutputProcessor::StoreType::Average,
    1352           71 :                                     surf.Name);
    1353          142 :                 SetupOutputVariable(state,
    1354              :                                     "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
    1355              :                                     Constant::Units::W,
    1356           71 :                                     state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
    1357              :                                     OutputProcessor::TimeStepType::Zone,
    1358              :                                     OutputProcessor::StoreType::Average,
    1359           71 :                                     surf.Name);
    1360              : 
    1361           71 :                 if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
    1362            1 :                     NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotSolidLayers;
    1363              :                 } else {
    1364           70 :                     NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotLayers;
    1365              :                 }
    1366          222 :                 for (I = 1; I <= NumOfLayers; ++I) {
    1367          151 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
    1368            9 :                         SetupOutputVariable(state,
    1369            6 :                                             format("Surface Window Total Absorbed Shortwave Radiation Rate Layer {}", I),
    1370              :                                             Constant::Units::W,
    1371            3 :                                             state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfLoop, I),
    1372              :                                             OutputProcessor::TimeStepType::Zone,
    1373              :                                             OutputProcessor::StoreType::Average,
    1374            3 :                                             surf.Name);
    1375              :                     }
    1376          151 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == 1)) {
    1377          219 :                         SetupOutputVariable(state,
    1378          146 :                                             format("Surface Window Front Face Temperature Layer {}", I),
    1379              :                                             Constant::Units::C,
    1380           73 :                                             state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfLoop, I),
    1381              :                                             OutputProcessor::TimeStepType::Zone,
    1382              :                                             OutputProcessor::StoreType::Average,
    1383           73 :                                             surf.Name);
    1384              :                     }
    1385          151 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == NumOfLayers)) {
    1386          219 :                         SetupOutputVariable(state,
    1387          146 :                                             format("Surface Window Back Face Temperature Layer {}", I),
    1388              :                                             Constant::Units::C,
    1389           73 :                                             state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfLoop, I),
    1390              :                                             OutputProcessor::TimeStepType::Zone,
    1391              :                                             OutputProcessor::StoreType::Average,
    1392           73 :                                             surf.Name);
    1393              :                     }
    1394              :                 }
    1395              : 
    1396          142 :                 SetupOutputVariable(state,
    1397              :                                     "Surface Window Transmitted Solar Radiation Rate",
    1398              :                                     Constant::Units::W,
    1399           71 :                                     s_surf->SurfWinTransSolar(SurfLoop),
    1400              :                                     OutputProcessor::TimeStepType::Zone,
    1401              :                                     OutputProcessor::StoreType::Average,
    1402           71 :                                     surf.Name);
    1403          142 :                 SetupOutputVariable(state,
    1404              :                                     "Surface Window Transmitted Beam Solar Radiation Rate",
    1405              :                                     Constant::Units::W,
    1406           71 :                                     s_surf->SurfWinBmSolar(SurfLoop),
    1407              :                                     OutputProcessor::TimeStepType::Zone,
    1408              :                                     OutputProcessor::StoreType::Average,
    1409           71 :                                     surf.Name);
    1410              : 
    1411              :                 // added TH 12/9/2009
    1412          142 :                 SetupOutputVariable(state,
    1413              :                                     "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
    1414              :                                     Constant::Units::W,
    1415           71 :                                     s_surf->SurfWinBmBmSolar(SurfLoop),
    1416              :                                     OutputProcessor::TimeStepType::Zone,
    1417              :                                     OutputProcessor::StoreType::Average,
    1418           71 :                                     surf.Name);
    1419          142 :                 SetupOutputVariable(state,
    1420              :                                     "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
    1421              :                                     Constant::Units::W,
    1422           71 :                                     s_surf->SurfWinBmDifSolar(SurfLoop),
    1423              :                                     OutputProcessor::TimeStepType::Zone,
    1424              :                                     OutputProcessor::StoreType::Average,
    1425           71 :                                     surf.Name);
    1426              : 
    1427          142 :                 SetupOutputVariable(state,
    1428              :                                     "Surface Window Transmitted Diffuse Solar Radiation Rate",
    1429              :                                     Constant::Units::W,
    1430           71 :                                     s_surf->SurfWinDifSolar(SurfLoop),
    1431              :                                     OutputProcessor::TimeStepType::Zone,
    1432              :                                     OutputProcessor::StoreType::Average,
    1433           71 :                                     surf.Name);
    1434          142 :                 SetupOutputVariable(state,
    1435              :                                     "Surface Window Heat Gain Rate",
    1436              :                                     Constant::Units::W,
    1437           71 :                                     s_surf->SurfWinHeatGainRep(SurfLoop),
    1438              :                                     OutputProcessor::TimeStepType::Zone,
    1439              :                                     OutputProcessor::StoreType::Average,
    1440           71 :                                     surf.Name);
    1441          142 :                 SetupOutputVariable(state,
    1442              :                                     "Surface Window Heat Loss Rate",
    1443              :                                     Constant::Units::W,
    1444           71 :                                     s_surf->SurfWinHeatLossRep(SurfLoop),
    1445              :                                     OutputProcessor::TimeStepType::Zone,
    1446              :                                     OutputProcessor::StoreType::Average,
    1447           71 :                                     surf.Name);
    1448          142 :                 SetupOutputVariable(state,
    1449              :                                     "Surface Window Gap Convective Heat Transfer Rate",
    1450              :                                     Constant::Units::W,
    1451           71 :                                     s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
    1452              :                                     OutputProcessor::TimeStepType::Zone,
    1453              :                                     OutputProcessor::StoreType::Average,
    1454           71 :                                     surf.Name);
    1455          142 :                 SetupOutputVariable(state,
    1456              :                                     "Surface Window Shading Device Absorbed Solar Radiation Rate",
    1457              :                                     Constant::Units::W,
    1458           71 :                                     s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
    1459              :                                     OutputProcessor::TimeStepType::Zone,
    1460              :                                     OutputProcessor::StoreType::Average,
    1461           71 :                                     surf.Name);
    1462          142 :                 SetupOutputVariable(state,
    1463              :                                     "Surface Window Net Heat Transfer Rate",
    1464              :                                     Constant::Units::W,
    1465           71 :                                     s_surf->SurfWinHeatGain(SurfLoop),
    1466              :                                     OutputProcessor::TimeStepType::Zone,
    1467              :                                     OutputProcessor::StoreType::Average,
    1468           71 :                                     surf.Name);
    1469              : 
    1470           71 :                 if (state.dataGlobal->DisplayAdvancedReportVariables) {
    1471              :                     // CurrentModuleObject='Windows/GlassDoors(Advanced)'
    1472            0 :                     SetupOutputVariable(state,
    1473              :                                         "Surface Window Inside Face Glazing Zone Convection Heat Gain Rate",
    1474              :                                         Constant::Units::W,
    1475            0 :                                         s_surf->SurfWinGainConvGlazToZoneRep(SurfLoop),
    1476              :                                         OutputProcessor::TimeStepType::Zone,
    1477              :                                         OutputProcessor::StoreType::Average,
    1478            0 :                                         surf.Name);
    1479            0 :                     SetupOutputVariable(state,
    1480              :                                         "Surface Window Inside Face Glazing Net Infrared Heat Transfer Rate",
    1481              :                                         Constant::Units::W,
    1482            0 :                                         s_surf->SurfWinGainIRGlazToZoneRep(SurfLoop),
    1483              :                                         OutputProcessor::TimeStepType::Zone,
    1484              :                                         OutputProcessor::StoreType::Average,
    1485            0 :                                         surf.Name);
    1486            0 :                     SetupOutputVariable(state,
    1487              :                                         "Surface Window Shortwave from Zone Back Out Window Heat Transfer Rate",
    1488              :                                         Constant::Units::W,
    1489            0 :                                         s_surf->SurfWinLossSWZoneToOutWinRep(SurfLoop),
    1490              :                                         OutputProcessor::TimeStepType::Zone,
    1491              :                                         OutputProcessor::StoreType::Average,
    1492            0 :                                         surf.Name);
    1493            0 :                     SetupOutputVariable(state,
    1494              :                                         "Surface Window Inside Face Frame and Divider Zone Heat Gain Rate",
    1495              :                                         Constant::Units::W,
    1496            0 :                                         s_surf->SurfWinGainFrameDividerToZoneRep(SurfLoop),
    1497              :                                         OutputProcessor::TimeStepType::Zone,
    1498              :                                         OutputProcessor::StoreType::Average,
    1499            0 :                                         surf.Name);
    1500            0 :                     SetupOutputVariable(state,
    1501              :                                         "Surface Window Inside Face Gap between Shade and Glazing Zone Convection Heat Gain Rate",
    1502              :                                         Constant::Units::W,
    1503            0 :                                         s_surf->SurfWinConvHeatFlowNatural(SurfLoop),
    1504              :                                         OutputProcessor::TimeStepType::Zone,
    1505              :                                         OutputProcessor::StoreType::Average,
    1506            0 :                                         surf.Name);
    1507            0 :                     SetupOutputVariable(state,
    1508              :                                         "Surface Window Inside Face Shade Zone Convection Heat Gain Rate",
    1509              :                                         Constant::Units::W,
    1510            0 :                                         s_surf->SurfWinGainConvShadeToZoneRep(SurfLoop),
    1511              :                                         OutputProcessor::TimeStepType::Zone,
    1512              :                                         OutputProcessor::StoreType::Average,
    1513            0 :                                         surf.Name);
    1514            0 :                     SetupOutputVariable(state,
    1515              :                                         "Surface Window Inside Face Shade Net Infrared Heat Transfer Rate",
    1516              :                                         Constant::Units::W,
    1517            0 :                                         s_surf->SurfWinGainIRShadeToZoneRep(SurfLoop),
    1518              :                                         OutputProcessor::TimeStepType::Zone,
    1519              :                                         OutputProcessor::StoreType::Average,
    1520            0 :                                         surf.Name);
    1521            0 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
    1522            0 :                         SetupOutputVariable(state,
    1523              :                                             "Surface Window Inside Face Other Convection Heat Gain Rate",
    1524              :                                             Constant::Units::W,
    1525            0 :                                             s_surf->SurfWinOtherConvHeatGain(SurfLoop),
    1526              :                                             OutputProcessor::TimeStepType::Zone,
    1527              :                                             OutputProcessor::StoreType::Average,
    1528            0 :                                             surf.Name);
    1529              :                     }
    1530              :                 }
    1531              : 
    1532              :                 // Added TH 12/23/2008 for thermochromic windows
    1533              :                 // CurrentModuleObject='Thermochromic Windows'
    1534           71 :                 if (state.dataConstruction->Construct(surf.Construction).isTCWindow) {
    1535            0 :                     SetupOutputVariable(state,
    1536              :                                         "Surface Window Thermochromic Layer Temperature",
    1537              :                                         Constant::Units::C,
    1538            0 :                                         s_surf->SurfWinTCLayerTemp(SurfLoop),
    1539              :                                         OutputProcessor::TimeStepType::Zone,
    1540              :                                         OutputProcessor::StoreType::Average,
    1541            0 :                                         surf.Name);
    1542            0 :                     SetupOutputVariable(state,
    1543              :                                         "Surface Window Thermochromic Layer Property Specification Temperature",
    1544              :                                         Constant::Units::C,
    1545            0 :                                         s_surf->SurfWinSpecTemp(SurfLoop),
    1546              :                                         OutputProcessor::TimeStepType::Zone,
    1547              :                                         OutputProcessor::StoreType::Average,
    1548            0 :                                         surf.Name);
    1549              :                 }
    1550              : 
    1551              :                 // Added TH 5/26/2009 for switchable windows to report switching factor (tinted level)
    1552              :                 // CurrentModuleObject='Switchable Windows'
    1553           71 :                 if (surf.HasShadeControl) {
    1554            8 :                     if (s_surf->WindowShadingControl(surf.activeWindowShadingControl).ShadingType == WinShadingType::SwitchableGlazing) {
    1555              :                         // IF (SurfaceWindow(SurfLoop)%ShadingFlag == WinShadingType::SwitchableGlazing) THEN  !ShadingFlag is not set to
    1556              :                         // WinShadingType::SwitchableGlazing yet!
    1557            0 :                         SetupOutputVariable(state,
    1558              :                                             "Surface Window Switchable Glazing Switching Factor",
    1559              :                                             Constant::Units::None,
    1560            0 :                                             s_surf->SurfWinSwitchingFactor(SurfLoop),
    1561              :                                             OutputProcessor::TimeStepType::Zone,
    1562              :                                             OutputProcessor::StoreType::Average,
    1563            0 :                                             surf.Name);
    1564            0 :                         SetupOutputVariable(state,
    1565              :                                             "Surface Window Switchable Glazing Visible Transmittance",
    1566              :                                             Constant::Units::None,
    1567            0 :                                             s_surf->SurfWinVisTransSelected(SurfLoop),
    1568              :                                             OutputProcessor::TimeStepType::Zone,
    1569              :                                             OutputProcessor::StoreType::Average,
    1570            0 :                                             surf.Name);
    1571              :                     }
    1572              :                 }
    1573              : 
    1574           71 :                 if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
    1575              :                     // CurrentModuleObject='Window Frames'
    1576           40 :                     SetupOutputVariable(state,
    1577              :                                         "Surface Window Frame Heat Gain Rate",
    1578              :                                         Constant::Units::W,
    1579           20 :                                         s_surf->SurfWinFrameHeatGain(SurfLoop),
    1580              :                                         OutputProcessor::TimeStepType::Zone,
    1581              :                                         OutputProcessor::StoreType::Average,
    1582           20 :                                         surf.Name);
    1583           40 :                     SetupOutputVariable(state,
    1584              :                                         "Surface Window Frame Heat Loss Rate",
    1585              :                                         Constant::Units::W,
    1586           20 :                                         s_surf->SurfWinFrameHeatLoss(SurfLoop),
    1587              :                                         OutputProcessor::TimeStepType::Zone,
    1588              :                                         OutputProcessor::StoreType::Average,
    1589           20 :                                         surf.Name);
    1590           40 :                     SetupOutputVariable(state,
    1591              :                                         "Surface Window Frame Inside Temperature",
    1592              :                                         Constant::Units::C,
    1593           20 :                                         s_surf->SurfWinFrameTempIn(SurfLoop),
    1594              :                                         OutputProcessor::TimeStepType::Zone,
    1595              :                                         OutputProcessor::StoreType::Average,
    1596           20 :                                         surf.Name);
    1597           40 :                     SetupOutputVariable(state,
    1598              :                                         "Surface Window Frame Outside Temperature",
    1599              :                                         Constant::Units::C,
    1600           20 :                                         s_surf->SurfWinFrameTempSurfOut(SurfLoop),
    1601              :                                         OutputProcessor::TimeStepType::Zone,
    1602              :                                         OutputProcessor::StoreType::Average,
    1603           20 :                                         surf.Name);
    1604              :                 }
    1605           71 :                 if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
    1606              :                     // CurrentModuleObject='Window Dividers'
    1607           40 :                     SetupOutputVariable(state,
    1608              :                                         "Surface Window Divider Heat Gain Rate",
    1609              :                                         Constant::Units::W,
    1610           20 :                                         s_surf->SurfWinDividerHeatGain(SurfLoop),
    1611              :                                         OutputProcessor::TimeStepType::Zone,
    1612              :                                         OutputProcessor::StoreType::Average,
    1613           20 :                                         surf.Name);
    1614           40 :                     SetupOutputVariable(state,
    1615              :                                         "Surface Window Divider Heat Loss Rate",
    1616              :                                         Constant::Units::W,
    1617           20 :                                         s_surf->SurfWinDividerHeatLoss(SurfLoop),
    1618              :                                         OutputProcessor::TimeStepType::Zone,
    1619              :                                         OutputProcessor::StoreType::Average,
    1620           20 :                                         surf.Name);
    1621           40 :                     SetupOutputVariable(state,
    1622              :                                         "Surface Window Divider Inside Temperature",
    1623              :                                         Constant::Units::C,
    1624           20 :                                         s_surf->SurfWinDividerTempIn(SurfLoop),
    1625              :                                         OutputProcessor::TimeStepType::Zone,
    1626              :                                         OutputProcessor::StoreType::Average,
    1627           20 :                                         surf.Name);
    1628           40 :                     SetupOutputVariable(state,
    1629              :                                         "Surface Window Divider Outside Temperature",
    1630              :                                         Constant::Units::C,
    1631           20 :                                         s_surf->SurfWinDividerTempSurfOut(SurfLoop),
    1632              :                                         OutputProcessor::TimeStepType::Zone,
    1633              :                                         OutputProcessor::StoreType::Average,
    1634           20 :                                         surf.Name);
    1635              :                 }
    1636              : 
    1637              :                 // CurrentModuleObject='Windows'
    1638              :                 // Energy
    1639          142 :                 SetupOutputVariable(state,
    1640              :                                     "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    1641              :                                     Constant::Units::J,
    1642           71 :                                     state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    1643              :                                     OutputProcessor::TimeStepType::Zone,
    1644              :                                     OutputProcessor::StoreType::Sum,
    1645           71 :                                     surf.Name);
    1646          142 :                 SetupOutputVariable(state,
    1647              :                                     "Surface Window Transmitted Solar Radiation Energy",
    1648              :                                     Constant::Units::J,
    1649           71 :                                     s_surf->SurfWinTransSolarEnergy(SurfLoop),
    1650              :                                     OutputProcessor::TimeStepType::Zone,
    1651              :                                     OutputProcessor::StoreType::Sum,
    1652           71 :                                     surf.Name);
    1653          142 :                 SetupOutputVariable(state,
    1654              :                                     "Surface Window Transmitted Beam Solar Radiation Energy",
    1655              :                                     Constant::Units::J,
    1656           71 :                                     s_surf->SurfWinBmSolarEnergy(SurfLoop),
    1657              :                                     OutputProcessor::TimeStepType::Zone,
    1658              :                                     OutputProcessor::StoreType::Sum,
    1659           71 :                                     surf.Name);
    1660              : 
    1661              :                 // added TH 12/9/2009
    1662          142 :                 SetupOutputVariable(state,
    1663              :                                     "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
    1664              :                                     Constant::Units::J,
    1665           71 :                                     s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
    1666              :                                     OutputProcessor::TimeStepType::Zone,
    1667              :                                     OutputProcessor::StoreType::Sum,
    1668           71 :                                     surf.Name);
    1669          142 :                 SetupOutputVariable(state,
    1670              :                                     "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
    1671              :                                     Constant::Units::J,
    1672           71 :                                     s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
    1673              :                                     OutputProcessor::TimeStepType::Zone,
    1674              :                                     OutputProcessor::StoreType::Sum,
    1675           71 :                                     surf.Name);
    1676              : 
    1677          142 :                 SetupOutputVariable(state,
    1678              :                                     "Surface Window Transmitted Diffuse Solar Radiation Energy",
    1679              :                                     Constant::Units::J,
    1680           71 :                                     s_surf->SurfWinDifSolarEnergy(SurfLoop),
    1681              :                                     OutputProcessor::TimeStepType::Zone,
    1682              :                                     OutputProcessor::StoreType::Sum,
    1683           71 :                                     surf.Name);
    1684          142 :                 SetupOutputVariable(state,
    1685              :                                     "Surface Window Heat Gain Energy",
    1686              :                                     Constant::Units::J,
    1687           71 :                                     s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
    1688              :                                     OutputProcessor::TimeStepType::Zone,
    1689              :                                     OutputProcessor::StoreType::Sum,
    1690           71 :                                     surf.Name);
    1691          142 :                 SetupOutputVariable(state,
    1692              :                                     "Surface Window Heat Loss Energy",
    1693              :                                     Constant::Units::J,
    1694           71 :                                     s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
    1695              :                                     OutputProcessor::TimeStepType::Zone,
    1696              :                                     OutputProcessor::StoreType::Sum,
    1697           71 :                                     surf.Name);
    1698          142 :                 SetupOutputVariable(state,
    1699              :                                     "Surface Window Gap Convective Heat Transfer Energy",
    1700              :                                     Constant::Units::J,
    1701           71 :                                     s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
    1702              :                                     OutputProcessor::TimeStepType::Zone,
    1703              :                                     OutputProcessor::StoreType::Sum,
    1704           71 :                                     surf.Name);
    1705          142 :                 SetupOutputVariable(state,
    1706              :                                     "Surface Window Shading Device Absorbed Solar Radiation Energy",
    1707              :                                     Constant::Units::J,
    1708           71 :                                     s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
    1709              :                                     OutputProcessor::TimeStepType::Zone,
    1710              :                                     OutputProcessor::StoreType::Sum,
    1711           71 :                                     surf.Name);
    1712          142 :                 SetupOutputVariable(state,
    1713              :                                     "Surface Window Net Heat Transfer Energy",
    1714              :                                     Constant::Units::J,
    1715           71 :                                     s_surf->SurfWinHeatTransferRepEnergy(SurfLoop),
    1716              :                                     OutputProcessor::TimeStepType::Zone,
    1717              :                                     OutputProcessor::StoreType::Sum,
    1718           71 :                                     surf.Name);
    1719              : 
    1720          142 :                 SetupOutputVariable(state,
    1721              :                                     "Surface Window System Solar Transmittance",
    1722              :                                     Constant::Units::None,
    1723           71 :                                     s_surf->SurfWinSysSolTransmittance(SurfLoop),
    1724              :                                     OutputProcessor::TimeStepType::Zone,
    1725              :                                     OutputProcessor::StoreType::Average,
    1726           71 :                                     surf.Name);
    1727          142 :                 SetupOutputVariable(state,
    1728              :                                     "Surface Window System Solar Reflectance",
    1729              :                                     Constant::Units::None,
    1730           71 :                                     s_surf->SurfWinSysSolReflectance(SurfLoop),
    1731              :                                     OutputProcessor::TimeStepType::Zone,
    1732              :                                     OutputProcessor::StoreType::Average,
    1733           71 :                                     surf.Name);
    1734          142 :                 SetupOutputVariable(state,
    1735              :                                     "Surface Window System Solar Absorptance",
    1736              :                                     Constant::Units::None,
    1737           71 :                                     s_surf->SurfWinSysSolAbsorptance(SurfLoop),
    1738              :                                     OutputProcessor::TimeStepType::Zone,
    1739              :                                     OutputProcessor::StoreType::Average,
    1740           71 :                                     surf.Name);
    1741           71 :                 SetupOutputVariable(state,
    1742              :                                     "Surface Window Inside Face Glazing Condensation Status",
    1743              :                                     Constant::Units::None,
    1744           71 :                                     s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
    1745              :                                     OutputProcessor::TimeStepType::Zone,
    1746              :                                     OutputProcessor::StoreType::Average,
    1747           71 :                                     surf.Name);
    1748           71 :                 SetupOutputVariable(state,
    1749              :                                     "Surface Window Inside Face Frame Condensation Status",
    1750              :                                     Constant::Units::None,
    1751           71 :                                     s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
    1752              :                                     OutputProcessor::TimeStepType::Zone,
    1753              :                                     OutputProcessor::StoreType::Average,
    1754           71 :                                     surf.Name);
    1755           71 :                 SetupOutputVariable(state,
    1756              :                                     "Surface Window Inside Face Divider Condensation Status",
    1757              :                                     Constant::Units::None,
    1758           71 :                                     s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
    1759              :                                     OutputProcessor::TimeStepType::Zone,
    1760              :                                     OutputProcessor::StoreType::Average,
    1761           71 :                                     surf.Name);
    1762              : 
    1763              :                 // Outside reveal report variables
    1764              :                 // IF (Surface(SurfLoop)%Reveal > 0.0) THEN
    1765          142 :                 SetupOutputVariable(state,
    1766              :                                     "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
    1767              :                                     Constant::Units::W,
    1768           71 :                                     s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
    1769              :                                     OutputProcessor::TimeStepType::Zone,
    1770              :                                     OutputProcessor::StoreType::Average,
    1771           71 :                                     surf.Name);
    1772              :                 // Energy
    1773          142 :                 SetupOutputVariable(state,
    1774              :                                     "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
    1775              :                                     Constant::Units::J,
    1776           71 :                                     s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
    1777              :                                     OutputProcessor::TimeStepType::Zone,
    1778              :                                     OutputProcessor::StoreType::Sum,
    1779           71 :                                     surf.Name);
    1780              :                 // ENDIF
    1781              : 
    1782              :                 // Inside reveal report variables
    1783           71 :                 if (s_surf->SurfWinInsideReveal(SurfLoop) > 0.0 || s_surf->SurfWinInsideSillDepth(SurfLoop) > 0.0) {
    1784            0 :                     SetupOutputVariable(state,
    1785              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
    1786              :                                         Constant::Units::W,
    1787            0 :                                         s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
    1788              :                                         OutputProcessor::TimeStepType::Zone,
    1789              :                                         OutputProcessor::StoreType::Average,
    1790            0 :                                         surf.Name);
    1791              :                     // Energy
    1792            0 :                     SetupOutputVariable(state,
    1793              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
    1794              :                                         Constant::Units::J,
    1795            0 :                                         s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
    1796              :                                         OutputProcessor::TimeStepType::Zone,
    1797              :                                         OutputProcessor::StoreType::Sum,
    1798            0 :                                         surf.Name);
    1799              : 
    1800              :                     // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
    1801              :                     // All reflected solar by the inside reveal is turned into diffuse
    1802            0 :                     SetupOutputVariable(state,
    1803              :                                         "Surface Window Inside Reveal Absorbed Beam Solar Radiation Rate",
    1804              :                                         Constant::Units::W,
    1805            0 :                                         s_surf->SurfWinBmSolAbsdInsRevealReport(SurfLoop),
    1806              :                                         OutputProcessor::TimeStepType::Zone,
    1807              :                                         OutputProcessor::StoreType::Average,
    1808            0 :                                         surf.Name);
    1809            0 :                     SetupOutputVariable(state,
    1810              :                                         "Surface Window Inside Reveal Reflected Diffuse Zone Solar Radiation Rate",
    1811              :                                         Constant::Units::W,
    1812            0 :                                         s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfLoop),
    1813              :                                         OutputProcessor::TimeStepType::Zone,
    1814              :                                         OutputProcessor::StoreType::Average,
    1815            0 :                                         surf.Name);
    1816            0 :                     SetupOutputVariable(state,
    1817              :                                         "Surface Window Inside Reveal Reflected Diffuse Frame Solar Radiation Rate",
    1818              :                                         Constant::Units::W,
    1819            0 :                                         s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfLoop),
    1820              :                                         OutputProcessor::TimeStepType::Zone,
    1821              :                                         OutputProcessor::StoreType::Average,
    1822            0 :                                         surf.Name);
    1823            0 :                     SetupOutputVariable(state,
    1824              :                                         "Surface Window Inside Reveal Reflected Diffuse Glazing Solar Radiation Rate",
    1825              :                                         Constant::Units::W,
    1826            0 :                                         s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfLoop),
    1827              :                                         OutputProcessor::TimeStepType::Zone,
    1828              :                                         OutputProcessor::StoreType::Average,
    1829            0 :                                         surf.Name);
    1830              :                 }
    1831              : 
    1832              :                 //     Output blind report variables only when blinds are used
    1833           71 :                 auto &surfShade = s_surf->surfShades(SurfLoop);
    1834           71 :                 if (surfShade.blind.matNum > 0) {
    1835              :                     // CurrentModuleObject='Window Blinds'
    1836           16 :                     SetupOutputVariable(state,
    1837              :                                         "Surface Window Blind Beam to Beam Solar Transmittance",
    1838              :                                         Constant::Units::None,
    1839            8 :                                         s_surf->SurfWinBlTsolBmBm(SurfLoop),
    1840              :                                         OutputProcessor::TimeStepType::Zone,
    1841              :                                         OutputProcessor::StoreType::Average,
    1842            8 :                                         surf.Name);
    1843           16 :                     SetupOutputVariable(state,
    1844              :                                         "Surface Window Blind Beam to Diffuse Solar Transmittance",
    1845              :                                         Constant::Units::None,
    1846            8 :                                         s_surf->SurfWinBlTsolBmDif(SurfLoop),
    1847              :                                         OutputProcessor::TimeStepType::Zone,
    1848              :                                         OutputProcessor::StoreType::Average,
    1849            8 :                                         surf.Name);
    1850           16 :                     SetupOutputVariable(state,
    1851              :                                         "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
    1852              :                                         Constant::Units::None,
    1853            8 :                                         s_surf->SurfWinBlTsolDifDif(SurfLoop),
    1854              :                                         OutputProcessor::TimeStepType::Zone,
    1855              :                                         OutputProcessor::StoreType::Average,
    1856            8 :                                         surf.Name);
    1857           16 :                     SetupOutputVariable(state,
    1858              :                                         "Surface Window Blind and Glazing System Beam Solar Transmittance",
    1859              :                                         Constant::Units::None,
    1860            8 :                                         s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
    1861              :                                         OutputProcessor::TimeStepType::Zone,
    1862              :                                         OutputProcessor::StoreType::Average,
    1863            8 :                                         surf.Name);
    1864           16 :                     SetupOutputVariable(state,
    1865              :                                         "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
    1866              :                                         Constant::Units::None,
    1867            8 :                                         s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
    1868              :                                         OutputProcessor::TimeStepType::Zone,
    1869              :                                         OutputProcessor::StoreType::Average,
    1870            8 :                                         surf.Name);
    1871              :                 }
    1872              : 
    1873              :                 //     Output screen report variables only when screens are used
    1874           71 :                 if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
    1875              :                     // CurrentModuleObject='Window Screens'
    1876            0 :                     SetupOutputVariable(state,
    1877              :                                         "Surface Window Screen Beam to Beam Solar Transmittance",
    1878              :                                         Constant::Units::None,
    1879            0 :                                         s_surf->SurfWinScTsolBmBm(SurfLoop),
    1880              :                                         OutputProcessor::TimeStepType::Zone,
    1881              :                                         OutputProcessor::StoreType::Average,
    1882            0 :                                         surf.Name);
    1883            0 :                     SetupOutputVariable(state,
    1884              :                                         "Surface Window Screen Beam to Diffuse Solar Transmittance",
    1885              :                                         Constant::Units::None,
    1886            0 :                                         s_surf->SurfWinScTsolBmDif(SurfLoop),
    1887              :                                         OutputProcessor::TimeStepType::Zone,
    1888              :                                         OutputProcessor::StoreType::Average,
    1889            0 :                                         surf.Name);
    1890            0 :                     SetupOutputVariable(state,
    1891              :                                         "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
    1892              :                                         Constant::Units::None,
    1893            0 :                                         s_surf->SurfWinScTsolDifDif(SurfLoop),
    1894              :                                         OutputProcessor::TimeStepType::Zone,
    1895              :                                         OutputProcessor::StoreType::Average,
    1896            0 :                                         surf.Name);
    1897            0 :                     SetupOutputVariable(state,
    1898              :                                         "Surface Window Screen and Glazing System Beam Solar Transmittance",
    1899              :                                         Constant::Units::None,
    1900            0 :                                         s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
    1901              :                                         OutputProcessor::TimeStepType::Zone,
    1902              :                                         OutputProcessor::StoreType::Average,
    1903            0 :                                         surf.Name);
    1904            0 :                     SetupOutputVariable(state,
    1905              :                                         "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
    1906              :                                         Constant::Units::None,
    1907            0 :                                         s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
    1908              :                                         OutputProcessor::TimeStepType::Zone,
    1909              :                                         OutputProcessor::StoreType::Average,
    1910            0 :                                         surf.Name);
    1911              :                 }
    1912              : 
    1913              :                 // CurrentModuleObject='Windows'
    1914          142 :                 SetupOutputVariable(state,
    1915              :                                     "Surface Window Solar Horizontal Profile Angle",
    1916              :                                     Constant::Units::deg,
    1917           71 :                                     s_surf->SurfWinProfileAngHor(SurfLoop),
    1918              :                                     OutputProcessor::TimeStepType::Zone,
    1919              :                                     OutputProcessor::StoreType::Average,
    1920           71 :                                     surf.Name);
    1921          142 :                 SetupOutputVariable(state,
    1922              :                                     "Surface Window Solar Vertical Profile Angle",
    1923              :                                     Constant::Units::deg,
    1924           71 :                                     s_surf->SurfWinProfileAngVert(SurfLoop),
    1925              :                                     OutputProcessor::TimeStepType::Zone,
    1926              :                                     OutputProcessor::StoreType::Average,
    1927           71 :                                     surf.Name);
    1928          142 :                 SetupOutputVariable(state,
    1929              :                                     "Surface Window Glazing Beam to Beam Solar Transmittance",
    1930              :                                     Constant::Units::None,
    1931           71 :                                     s_surf->SurfWinGlTsolBmBm(SurfLoop),
    1932              :                                     OutputProcessor::TimeStepType::Zone,
    1933              :                                     OutputProcessor::StoreType::Average,
    1934           71 :                                     surf.Name);
    1935          142 :                 SetupOutputVariable(state,
    1936              :                                     "Surface Window Glazing Beam to Diffuse Solar Transmittance",
    1937              :                                     Constant::Units::None,
    1938           71 :                                     s_surf->SurfWinGlTsolBmDif(SurfLoop),
    1939              :                                     OutputProcessor::TimeStepType::Zone,
    1940              :                                     OutputProcessor::StoreType::Average,
    1941           71 :                                     surf.Name);
    1942          142 :                 SetupOutputVariable(state,
    1943              :                                     "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
    1944              :                                     Constant::Units::None,
    1945           71 :                                     s_surf->SurfWinGlTsolDifDif(SurfLoop),
    1946              :                                     OutputProcessor::TimeStepType::Zone,
    1947              :                                     OutputProcessor::StoreType::Average,
    1948           71 :                                     surf.Name);
    1949           71 :                 SetupOutputVariable(state,
    1950              :                                     "Surface Window Model Solver Iteration Count",
    1951              :                                     Constant::Units::None,
    1952           71 :                                     s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
    1953              :                                     OutputProcessor::TimeStepType::Zone,
    1954              :                                     OutputProcessor::StoreType::Average,
    1955           71 :                                     surf.Name);
    1956              :             } else { // Not ExtSolar
    1957            2 :                 if (state.dataGlobal->DisplayAdvancedReportVariables) {
    1958              :                     // CurrentModuleObject='InteriorWindows(Advanced)'
    1959            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    1960            0 :                         SetupOutputVariable(state,
    1961              :                                             "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    1962              :                                             Constant::Units::W,
    1963            0 :                                             state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    1964              :                                             OutputProcessor::TimeStepType::Zone,
    1965              :                                             OutputProcessor::StoreType::Average,
    1966            0 :                                             surf.Name);
    1967              :                     }
    1968            0 :                     SetupOutputVariable(state,
    1969              :                                         "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
    1970              :                                         Constant::Units::W,
    1971            0 :                                         state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
    1972              :                                         OutputProcessor::TimeStepType::Zone,
    1973              :                                         OutputProcessor::StoreType::Average,
    1974            0 :                                         surf.Name);
    1975              : 
    1976            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    1977            0 :                         SetupOutputVariable(state,
    1978              :                                             "Surface Window Transmitted Solar Radiation Rate",
    1979              :                                             Constant::Units::W,
    1980            0 :                                             s_surf->SurfWinTransSolar(SurfLoop),
    1981              :                                             OutputProcessor::TimeStepType::Zone,
    1982              :                                             OutputProcessor::StoreType::Average,
    1983            0 :                                             surf.Name);
    1984              :                     }
    1985            0 :                     SetupOutputVariable(state,
    1986              :                                         "Surface Window Transmitted Beam Solar Radiation Rate",
    1987              :                                         Constant::Units::W,
    1988            0 :                                         s_surf->SurfWinBmSolar(SurfLoop),
    1989              :                                         OutputProcessor::TimeStepType::Zone,
    1990              :                                         OutputProcessor::StoreType::Average,
    1991            0 :                                         surf.Name);
    1992              : 
    1993              :                     // added TH 12/9/2009
    1994            0 :                     SetupOutputVariable(state,
    1995              :                                         "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
    1996              :                                         Constant::Units::W,
    1997            0 :                                         s_surf->SurfWinBmBmSolar(SurfLoop),
    1998              :                                         OutputProcessor::TimeStepType::Zone,
    1999              :                                         OutputProcessor::StoreType::Average,
    2000            0 :                                         surf.Name);
    2001            0 :                     SetupOutputVariable(state,
    2002              :                                         "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
    2003              :                                         Constant::Units::W,
    2004            0 :                                         s_surf->SurfWinBmDifSolar(SurfLoop),
    2005              :                                         OutputProcessor::TimeStepType::Zone,
    2006              :                                         OutputProcessor::StoreType::Average,
    2007            0 :                                         surf.Name);
    2008              : 
    2009            0 :                     SetupOutputVariable(state,
    2010              :                                         "Surface Window Transmitted Diffuse Solar Radiation Rate",
    2011              :                                         Constant::Units::W,
    2012            0 :                                         s_surf->SurfWinDifSolar(SurfLoop),
    2013              :                                         OutputProcessor::TimeStepType::Zone,
    2014              :                                         OutputProcessor::StoreType::Average,
    2015            0 :                                         surf.Name);
    2016            0 :                     SetupOutputVariable(state,
    2017              :                                         "Surface Window Heat Gain Rate",
    2018              :                                         Constant::Units::W,
    2019            0 :                                         s_surf->SurfWinHeatGainRep(SurfLoop),
    2020              :                                         OutputProcessor::TimeStepType::Zone,
    2021              :                                         OutputProcessor::StoreType::Average,
    2022            0 :                                         surf.Name);
    2023            0 :                     SetupOutputVariable(state,
    2024              :                                         "Surface Window Heat Loss Rate",
    2025              :                                         Constant::Units::W,
    2026            0 :                                         s_surf->SurfWinHeatLossRep(SurfLoop),
    2027              :                                         OutputProcessor::TimeStepType::Zone,
    2028              :                                         OutputProcessor::StoreType::Average,
    2029            0 :                                         surf.Name);
    2030            0 :                     SetupOutputVariable(state,
    2031              :                                         "Surface Window Gap Convective Heat Transfer Rate",
    2032              :                                         Constant::Units::W,
    2033            0 :                                         s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
    2034              :                                         OutputProcessor::TimeStepType::Zone,
    2035              :                                         OutputProcessor::StoreType::Average,
    2036            0 :                                         surf.Name);
    2037            0 :                     SetupOutputVariable(state,
    2038              :                                         "Surface Window Shading Device Absorbed Solar Radiation Rate",
    2039              :                                         Constant::Units::W,
    2040            0 :                                         s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
    2041              :                                         OutputProcessor::TimeStepType::Zone,
    2042              :                                         OutputProcessor::StoreType::Average,
    2043            0 :                                         surf.Name);
    2044            0 :                     if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
    2045            0 :                         SetupOutputVariable(state,
    2046              :                                             "Surface Window Frame Heat Gain Rate",
    2047              :                                             Constant::Units::W,
    2048            0 :                                             s_surf->SurfWinFrameHeatGain(SurfLoop),
    2049              :                                             OutputProcessor::TimeStepType::Zone,
    2050              :                                             OutputProcessor::StoreType::Average,
    2051            0 :                                             surf.Name);
    2052            0 :                         SetupOutputVariable(state,
    2053              :                                             "Surface Window Frame Heat Loss Rate",
    2054              :                                             Constant::Units::W,
    2055            0 :                                             s_surf->SurfWinFrameHeatLoss(SurfLoop),
    2056              :                                             OutputProcessor::TimeStepType::Zone,
    2057              :                                             OutputProcessor::StoreType::Average,
    2058            0 :                                             surf.Name);
    2059            0 :                         SetupOutputVariable(state,
    2060              :                                             "Surface Window Frame Inside Temperature",
    2061              :                                             Constant::Units::C,
    2062            0 :                                             s_surf->SurfWinFrameTempIn(SurfLoop),
    2063              :                                             OutputProcessor::TimeStepType::Zone,
    2064              :                                             OutputProcessor::StoreType::Average,
    2065            0 :                                             surf.Name);
    2066            0 :                         SetupOutputVariable(state,
    2067              :                                             "Surface Window Frame Outside Temperature",
    2068              :                                             Constant::Units::C,
    2069            0 :                                             s_surf->SurfWinFrameTempSurfOut(SurfLoop),
    2070              :                                             OutputProcessor::TimeStepType::Zone,
    2071              :                                             OutputProcessor::StoreType::Average,
    2072            0 :                                             surf.Name);
    2073              :                     }
    2074            0 :                     if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
    2075            0 :                         SetupOutputVariable(state,
    2076              :                                             "Surface Window Divider Heat Gain Rate",
    2077              :                                             Constant::Units::W,
    2078            0 :                                             s_surf->SurfWinDividerHeatGain(SurfLoop),
    2079              :                                             OutputProcessor::TimeStepType::Zone,
    2080              :                                             OutputProcessor::StoreType::Average,
    2081            0 :                                             surf.Name);
    2082            0 :                         SetupOutputVariable(state,
    2083              :                                             "Surface Window Divider Heat Loss Rate",
    2084              :                                             Constant::Units::W,
    2085            0 :                                             s_surf->SurfWinDividerHeatLoss(SurfLoop),
    2086              :                                             OutputProcessor::TimeStepType::Zone,
    2087              :                                             OutputProcessor::StoreType::Average,
    2088            0 :                                             surf.Name);
    2089            0 :                         SetupOutputVariable(state,
    2090              :                                             "Surface Window Divider Inside Temperature",
    2091              :                                             Constant::Units::C,
    2092            0 :                                             s_surf->SurfWinDividerTempIn(SurfLoop),
    2093              :                                             OutputProcessor::TimeStepType::Zone,
    2094              :                                             OutputProcessor::StoreType::Average,
    2095            0 :                                             surf.Name);
    2096            0 :                         SetupOutputVariable(state,
    2097              :                                             "Surface Window Divider Outside Temperature",
    2098              :                                             Constant::Units::C,
    2099            0 :                                             s_surf->SurfWinDividerTempSurfOut(SurfLoop),
    2100              :                                             OutputProcessor::TimeStepType::Zone,
    2101              :                                             OutputProcessor::StoreType::Average,
    2102            0 :                                             surf.Name);
    2103              :                     }
    2104              :                     // Energy
    2105              : 
    2106            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    2107            0 :                         SetupOutputVariable(state,
    2108              :                                             "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    2109              :                                             Constant::Units::J,
    2110            0 :                                             state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    2111              :                                             OutputProcessor::TimeStepType::Zone,
    2112              :                                             OutputProcessor::StoreType::Sum,
    2113            0 :                                             surf.Name);
    2114              :                     }
    2115              : 
    2116            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    2117            0 :                         SetupOutputVariable(state,
    2118              :                                             "Surface Window Transmitted Solar Radiation Energy",
    2119              :                                             Constant::Units::J,
    2120            0 :                                             s_surf->SurfWinTransSolarEnergy(SurfLoop),
    2121              :                                             OutputProcessor::TimeStepType::Zone,
    2122              :                                             OutputProcessor::StoreType::Sum,
    2123            0 :                                             surf.Name);
    2124              :                     }
    2125            0 :                     SetupOutputVariable(state,
    2126              :                                         "Surface Window Transmitted Beam Solar Radiation Energy",
    2127              :                                         Constant::Units::J,
    2128            0 :                                         s_surf->SurfWinBmSolarEnergy(SurfLoop),
    2129              :                                         OutputProcessor::TimeStepType::Zone,
    2130              :                                         OutputProcessor::StoreType::Sum,
    2131            0 :                                         surf.Name);
    2132              : 
    2133            0 :                     SetupOutputVariable(state,
    2134              :                                         "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
    2135              :                                         Constant::Units::J,
    2136            0 :                                         s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
    2137              :                                         OutputProcessor::TimeStepType::Zone,
    2138              :                                         OutputProcessor::StoreType::Sum,
    2139            0 :                                         surf.Name);
    2140            0 :                     SetupOutputVariable(state,
    2141              :                                         "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
    2142              :                                         Constant::Units::J,
    2143            0 :                                         s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
    2144              :                                         OutputProcessor::TimeStepType::Zone,
    2145              :                                         OutputProcessor::StoreType::Sum,
    2146            0 :                                         surf.Name);
    2147              : 
    2148            0 :                     SetupOutputVariable(state,
    2149              :                                         "Surface Window Transmitted Diffuse Solar Radiation Energy",
    2150              :                                         Constant::Units::J,
    2151            0 :                                         s_surf->SurfWinDifSolarEnergy(SurfLoop),
    2152              :                                         OutputProcessor::TimeStepType::Zone,
    2153              :                                         OutputProcessor::StoreType::Sum,
    2154            0 :                                         surf.Name);
    2155            0 :                     SetupOutputVariable(state,
    2156              :                                         "Surface Window Heat Gain Energy",
    2157              :                                         Constant::Units::J,
    2158            0 :                                         s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
    2159              :                                         OutputProcessor::TimeStepType::Zone,
    2160              :                                         OutputProcessor::StoreType::Sum,
    2161            0 :                                         surf.Name);
    2162            0 :                     SetupOutputVariable(state,
    2163              :                                         "Surface Window Heat Loss Energy",
    2164              :                                         Constant::Units::J,
    2165            0 :                                         s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
    2166              :                                         OutputProcessor::TimeStepType::Zone,
    2167              :                                         OutputProcessor::StoreType::Sum,
    2168            0 :                                         surf.Name);
    2169            0 :                     SetupOutputVariable(state,
    2170              :                                         "Surface Window Gap Convective Heat Transfer Energy",
    2171              :                                         Constant::Units::J,
    2172            0 :                                         s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
    2173              :                                         OutputProcessor::TimeStepType::Zone,
    2174              :                                         OutputProcessor::StoreType::Sum,
    2175            0 :                                         surf.Name);
    2176            0 :                     SetupOutputVariable(state,
    2177              :                                         "Surface Window Shading Device Absorbed Solar Radiation Energy",
    2178              :                                         Constant::Units::J,
    2179            0 :                                         s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
    2180              :                                         OutputProcessor::TimeStepType::Zone,
    2181              :                                         OutputProcessor::StoreType::Sum,
    2182            0 :                                         surf.Name);
    2183              : 
    2184            0 :                     SetupOutputVariable(state,
    2185              :                                         "Surface Window System Solar Transmittance",
    2186              :                                         Constant::Units::None,
    2187            0 :                                         s_surf->SurfWinSysSolTransmittance(SurfLoop),
    2188              :                                         OutputProcessor::TimeStepType::Zone,
    2189              :                                         OutputProcessor::StoreType::Average,
    2190            0 :                                         surf.Name);
    2191            0 :                     SetupOutputVariable(state,
    2192              :                                         "Surface Window System Solar Reflectance",
    2193              :                                         Constant::Units::None,
    2194            0 :                                         s_surf->SurfWinSysSolReflectance(SurfLoop),
    2195              :                                         OutputProcessor::TimeStepType::Zone,
    2196              :                                         OutputProcessor::StoreType::Average,
    2197            0 :                                         surf.Name);
    2198            0 :                     SetupOutputVariable(state,
    2199              :                                         "Surface Window System Solar Absorptance",
    2200              :                                         Constant::Units::None,
    2201            0 :                                         s_surf->SurfWinSysSolAbsorptance(SurfLoop),
    2202              :                                         OutputProcessor::TimeStepType::Zone,
    2203              :                                         OutputProcessor::StoreType::Average,
    2204            0 :                                         surf.Name);
    2205            0 :                     SetupOutputVariable(state,
    2206              :                                         "Surface Window Inside Face Glazing Condensation Status",
    2207              :                                         Constant::Units::None,
    2208            0 :                                         s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
    2209              :                                         OutputProcessor::TimeStepType::Zone,
    2210              :                                         OutputProcessor::StoreType::Average,
    2211            0 :                                         surf.Name);
    2212            0 :                     SetupOutputVariable(state,
    2213              :                                         "Surface Window Inside Face Frame Condensation Status",
    2214              :                                         Constant::Units::None,
    2215            0 :                                         s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
    2216              :                                         OutputProcessor::TimeStepType::Zone,
    2217              :                                         OutputProcessor::StoreType::Average,
    2218            0 :                                         surf.Name);
    2219            0 :                     SetupOutputVariable(state,
    2220              :                                         "Surface Window Inside Face Divider Condensation Status",
    2221              :                                         Constant::Units::None,
    2222            0 :                                         s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
    2223              :                                         OutputProcessor::TimeStepType::Zone,
    2224              :                                         OutputProcessor::StoreType::Average,
    2225            0 :                                         surf.Name);
    2226            0 :                     SetupOutputVariable(state,
    2227              :                                         "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
    2228              :                                         Constant::Units::W,
    2229            0 :                                         s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
    2230              :                                         OutputProcessor::TimeStepType::Zone,
    2231              :                                         OutputProcessor::StoreType::Average,
    2232            0 :                                         surf.Name);
    2233            0 :                     SetupOutputVariable(state,
    2234              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
    2235              :                                         Constant::Units::W,
    2236            0 :                                         s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
    2237              :                                         OutputProcessor::TimeStepType::Zone,
    2238              :                                         OutputProcessor::StoreType::Average,
    2239            0 :                                         surf.Name);
    2240              :                     // Energy
    2241            0 :                     SetupOutputVariable(state,
    2242              :                                         "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
    2243              :                                         Constant::Units::J,
    2244            0 :                                         s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
    2245              :                                         OutputProcessor::TimeStepType::Zone,
    2246              :                                         OutputProcessor::StoreType::Sum,
    2247            0 :                                         surf.Name);
    2248            0 :                     SetupOutputVariable(state,
    2249              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
    2250              :                                         Constant::Units::J,
    2251            0 :                                         s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
    2252              :                                         OutputProcessor::TimeStepType::Zone,
    2253              :                                         OutputProcessor::StoreType::Sum,
    2254            0 :                                         surf.Name);
    2255              : 
    2256              :                     //     Output blind report variables only when blinds are used
    2257            0 :                     auto &surfShade = s_surf->surfShades(SurfLoop);
    2258            0 :                     if (surfShade.blind.matNum > 0) {
    2259            0 :                         SetupOutputVariable(state,
    2260              :                                             "Surface Window Blind Beam to Beam Solar Transmittance",
    2261              :                                             Constant::Units::None,
    2262            0 :                                             s_surf->SurfWinBlTsolBmBm(SurfLoop),
    2263              :                                             OutputProcessor::TimeStepType::Zone,
    2264              :                                             OutputProcessor::StoreType::Average,
    2265            0 :                                             surf.Name);
    2266            0 :                         SetupOutputVariable(state,
    2267              :                                             "Surface Window Blind Beam to Diffuse Solar Transmittance",
    2268              :                                             Constant::Units::None,
    2269            0 :                                             s_surf->SurfWinBlTsolBmDif(SurfLoop),
    2270              :                                             OutputProcessor::TimeStepType::Zone,
    2271              :                                             OutputProcessor::StoreType::Average,
    2272            0 :                                             surf.Name);
    2273            0 :                         SetupOutputVariable(state,
    2274              :                                             "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
    2275              :                                             Constant::Units::None,
    2276            0 :                                             s_surf->SurfWinBlTsolDifDif(SurfLoop),
    2277              :                                             OutputProcessor::TimeStepType::Zone,
    2278              :                                             OutputProcessor::StoreType::Average,
    2279            0 :                                             surf.Name);
    2280            0 :                         SetupOutputVariable(state,
    2281              :                                             "Surface Window Blind and Glazing System Beam Solar Transmittance",
    2282              :                                             Constant::Units::None,
    2283            0 :                                             s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
    2284              :                                             OutputProcessor::TimeStepType::Zone,
    2285              :                                             OutputProcessor::StoreType::Average,
    2286            0 :                                             surf.Name);
    2287            0 :                         SetupOutputVariable(state,
    2288              :                                             "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
    2289              :                                             Constant::Units::None,
    2290            0 :                                             s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
    2291              :                                             OutputProcessor::TimeStepType::Zone,
    2292              :                                             OutputProcessor::StoreType::Average,
    2293            0 :                                             surf.Name);
    2294              :                     }
    2295              : 
    2296              :                     //     Output screen report variables only when screens are used
    2297            0 :                     if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
    2298            0 :                         SetupOutputVariable(state,
    2299              :                                             "Surface Window Screen Beam to Beam Solar Transmittance",
    2300              :                                             Constant::Units::None,
    2301            0 :                                             s_surf->SurfWinScTsolBmBm(SurfLoop),
    2302              :                                             OutputProcessor::TimeStepType::Zone,
    2303              :                                             OutputProcessor::StoreType::Average,
    2304            0 :                                             surf.Name);
    2305            0 :                         SetupOutputVariable(state,
    2306              :                                             "Surface Window Screen Beam to Diffuse Solar Transmittance",
    2307              :                                             Constant::Units::None,
    2308            0 :                                             s_surf->SurfWinScTsolBmDif(SurfLoop),
    2309              :                                             OutputProcessor::TimeStepType::Zone,
    2310              :                                             OutputProcessor::StoreType::Average,
    2311            0 :                                             surf.Name);
    2312            0 :                         SetupOutputVariable(state,
    2313              :                                             "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
    2314              :                                             Constant::Units::None,
    2315            0 :                                             s_surf->SurfWinScTsolDifDif(SurfLoop),
    2316              :                                             OutputProcessor::TimeStepType::Zone,
    2317              :                                             OutputProcessor::StoreType::Average,
    2318            0 :                                             surf.Name);
    2319            0 :                         SetupOutputVariable(state,
    2320              :                                             "Surface Window Screen and Glazing System Beam Solar Transmittance",
    2321              :                                             Constant::Units::None,
    2322            0 :                                             s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
    2323              :                                             OutputProcessor::TimeStepType::Zone,
    2324              :                                             OutputProcessor::StoreType::Average,
    2325            0 :                                             surf.Name);
    2326            0 :                         SetupOutputVariable(state,
    2327              :                                             "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
    2328              :                                             Constant::Units::None,
    2329            0 :                                             s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
    2330              :                                             OutputProcessor::TimeStepType::Zone,
    2331              :                                             OutputProcessor::StoreType::Average,
    2332            0 :                                             surf.Name);
    2333              :                     }
    2334              : 
    2335            0 :                     SetupOutputVariable(state,
    2336              :                                         "Surface Window Solar Horizontal Profile Angle",
    2337              :                                         Constant::Units::deg,
    2338            0 :                                         s_surf->SurfWinProfileAngHor(SurfLoop),
    2339              :                                         OutputProcessor::TimeStepType::Zone,
    2340              :                                         OutputProcessor::StoreType::Average,
    2341            0 :                                         surf.Name);
    2342            0 :                     SetupOutputVariable(state,
    2343              :                                         "Surface Window Solar Vertical Profile Angle",
    2344              :                                         Constant::Units::deg,
    2345            0 :                                         s_surf->SurfWinProfileAngVert(SurfLoop),
    2346              :                                         OutputProcessor::TimeStepType::Zone,
    2347              :                                         OutputProcessor::StoreType::Average,
    2348            0 :                                         surf.Name);
    2349            0 :                     SetupOutputVariable(state,
    2350              :                                         "Surface Window Glazing Beam to Beam Solar Transmittance",
    2351              :                                         Constant::Units::None,
    2352            0 :                                         s_surf->SurfWinGlTsolBmBm(SurfLoop),
    2353              :                                         OutputProcessor::TimeStepType::Zone,
    2354              :                                         OutputProcessor::StoreType::Average,
    2355            0 :                                         surf.Name);
    2356            0 :                     SetupOutputVariable(state,
    2357              :                                         "Surface Window Glazing Beam to Diffuse Solar Transmittance",
    2358              :                                         Constant::Units::None,
    2359            0 :                                         s_surf->SurfWinGlTsolBmDif(SurfLoop),
    2360              :                                         OutputProcessor::TimeStepType::Zone,
    2361              :                                         OutputProcessor::StoreType::Average,
    2362            0 :                                         surf.Name);
    2363            0 :                     SetupOutputVariable(state,
    2364              :                                         "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
    2365              :                                         Constant::Units::None,
    2366            0 :                                         s_surf->SurfWinGlTsolDifDif(SurfLoop),
    2367              :                                         OutputProcessor::TimeStepType::Zone,
    2368              :                                         OutputProcessor::StoreType::Average,
    2369            0 :                                         surf.Name);
    2370            0 :                     SetupOutputVariable(state,
    2371              :                                         "Surface Window Model Solver Iteration Count",
    2372              :                                         Constant::Units::None,
    2373            0 :                                         s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
    2374              :                                         OutputProcessor::TimeStepType::Zone,
    2375              :                                         OutputProcessor::StoreType::Average,
    2376            0 :                                         surf.Name);
    2377              :                 }
    2378              :             } // end non extsolar reporting as advanced variables
    2379              :         } // Window Reporting
    2380          940 :         if (surf.Class == SurfaceClass::Window && surf.ExtBoundCond > 0 && surf.ExtBoundCond != SurfLoop) { // Interzone window
    2381              :                                                                                                             // CurrentModuleObject='InterzoneWindows'
    2382            0 :             SetupOutputVariable(state,
    2383              :                                 "Surface Window Transmitted Beam Solar Radiation Rate",
    2384              :                                 Constant::Units::W,
    2385            0 :                                 s_surf->SurfWinBmSolTransThruIntWinRep(SurfLoop),
    2386              :                                 OutputProcessor::TimeStepType::Zone,
    2387              :                                 OutputProcessor::StoreType::Average,
    2388            0 :                                 surf.Name);
    2389              :             // energy
    2390            0 :             SetupOutputVariable(state,
    2391              :                                 "Surface Window Transmitted Beam Solar Radiation Energy",
    2392              :                                 Constant::Units::J,
    2393            0 :                                 s_surf->SurfWinBmSolTransThruIntWinRepEnergy(SurfLoop),
    2394              :                                 OutputProcessor::TimeStepType::Zone,
    2395              :                                 OutputProcessor::StoreType::Sum,
    2396            0 :                                 surf.Name);
    2397              :         }
    2398          940 :         if (surf.Class == SurfaceClass::TDD_Dome && surf.ExtSolar) {
    2399              :             // CurrentModuleObject='TDD Domes'
    2400            4 :             SetupOutputVariable(state,
    2401              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    2402              :                                 Constant::Units::W,
    2403            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    2404              :                                 OutputProcessor::TimeStepType::Zone,
    2405              :                                 OutputProcessor::StoreType::Average,
    2406            2 :                                 surf.Name);
    2407            4 :             SetupOutputVariable(state,
    2408              :                                 "Surface Window Transmitted Solar Radiation Rate",
    2409              :                                 Constant::Units::W,
    2410            2 :                                 s_surf->SurfWinTransSolar(SurfLoop),
    2411              :                                 OutputProcessor::TimeStepType::Zone,
    2412              :                                 OutputProcessor::StoreType::Average,
    2413            2 :                                 surf.Name);
    2414              :             // energy
    2415            4 :             SetupOutputVariable(state,
    2416              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    2417              :                                 Constant::Units::J,
    2418            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    2419              :                                 OutputProcessor::TimeStepType::Zone,
    2420              :                                 OutputProcessor::StoreType::Sum,
    2421            2 :                                 surf.Name);
    2422            4 :             SetupOutputVariable(state,
    2423              :                                 "Surface Window Transmitted Solar Radiation Energy",
    2424              :                                 Constant::Units::J,
    2425            2 :                                 s_surf->SurfWinTransSolarEnergy(SurfLoop),
    2426              :                                 OutputProcessor::TimeStepType::Zone,
    2427              :                                 OutputProcessor::StoreType::Sum,
    2428            2 :                                 surf.Name);
    2429              :         }
    2430          940 :         if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    2431              :             // CurrentModuleObject='TDD Diffusers'
    2432            4 :             SetupOutputVariable(state,
    2433              :                                 "Surface Outside Face Incident Solar Radiation Rate per Area",
    2434              :                                 Constant::Units::W_m2,
    2435            2 :                                 state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
    2436              :                                 OutputProcessor::TimeStepType::Zone,
    2437              :                                 OutputProcessor::StoreType::Average,
    2438            2 :                                 surf.Name);
    2439            4 :             SetupOutputVariable(state,
    2440              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    2441              :                                 Constant::Units::W,
    2442            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    2443              :                                 OutputProcessor::TimeStepType::Zone,
    2444              :                                 OutputProcessor::StoreType::Average,
    2445            2 :                                 surf.Name);
    2446            4 :             SetupOutputVariable(state,
    2447              :                                 "Surface Window Transmitted Solar Radiation Rate",
    2448              :                                 Constant::Units::W,
    2449            2 :                                 s_surf->SurfWinTransSolar(SurfLoop),
    2450              :                                 OutputProcessor::TimeStepType::Zone,
    2451              :                                 OutputProcessor::StoreType::Average,
    2452            2 :                                 surf.Name);
    2453              :             // energy
    2454            4 :             SetupOutputVariable(state,
    2455              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    2456              :                                 Constant::Units::J,
    2457            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    2458              :                                 OutputProcessor::TimeStepType::Zone,
    2459              :                                 OutputProcessor::StoreType::Sum,
    2460            2 :                                 surf.Name);
    2461            4 :             SetupOutputVariable(state,
    2462              :                                 "Surface Window Transmitted Solar Radiation Energy",
    2463              :                                 Constant::Units::J,
    2464            2 :                                 s_surf->SurfWinTransSolarEnergy(SurfLoop),
    2465              :                                 OutputProcessor::TimeStepType::Zone,
    2466              :                                 OutputProcessor::StoreType::Sum,
    2467            2 :                                 surf.Name);
    2468              :         }
    2469              :     }
    2470              : 
    2471         1151 :     for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
    2472         1010 :         auto &surf = s_surf->Surface(SurfLoop);
    2473         1010 :         if (!surf.HeatTransSurf) {
    2474           70 :             continue;
    2475              :         }
    2476              :         // CurrentModuleObject='Surfaces'
    2477         1880 :         SetupOutputVariable(state,
    2478              :                             "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate per Area",
    2479              :                             Constant::Units::W_m2,
    2480          940 :                             state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfLoop),
    2481              :                             OutputProcessor::TimeStepType::Zone,
    2482              :                             OutputProcessor::StoreType::Average,
    2483          940 :                             surf.Name);
    2484         1880 :         SetupOutputVariable(state,
    2485              :                             "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate",
    2486              :                             Constant::Units::W,
    2487          940 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfLoop),
    2488              :                             OutputProcessor::TimeStepType::Zone,
    2489              :                             OutputProcessor::StoreType::Average,
    2490          940 :                             surf.Name);
    2491         1880 :         SetupOutputVariable(state,
    2492              :                             "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate per Area",
    2493              :                             Constant::Units::W_m2,
    2494          940 :                             state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfLoop),
    2495              :                             OutputProcessor::TimeStepType::Zone,
    2496              :                             OutputProcessor::StoreType::Average,
    2497          940 :                             surf.Name);
    2498         1880 :         SetupOutputVariable(state,
    2499              :                             "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate",
    2500              :                             Constant::Units::W,
    2501          940 :                             state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfLoop),
    2502              :                             OutputProcessor::TimeStepType::Zone,
    2503              :                             OutputProcessor::StoreType::Average,
    2504          940 :                             surf.Name);
    2505         1880 :         SetupOutputVariable(state,
    2506              :                             "Surface Inside Face Initial Transmitted Diffuse Absorbed Solar Radiation Rate",
    2507              :                             Constant::Units::W,
    2508          940 :                             state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfLoop),
    2509              :                             OutputProcessor::TimeStepType::Zone,
    2510              :                             OutputProcessor::StoreType::Average,
    2511          940 :                             surf.Name);
    2512         1880 :         SetupOutputVariable(state,
    2513              :                             "Surface Inside Face Initial Transmitted Diffuse Transmitted Out Window Solar Radiation Rate",
    2514              :                             Constant::Units::W,
    2515          940 :                             state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfLoop),
    2516              :                             OutputProcessor::TimeStepType::Zone,
    2517              :                             OutputProcessor::StoreType::Average,
    2518          940 :                             surf.Name);
    2519         1880 :         SetupOutputVariable(state,
    2520              :                             "Surface Inside Face Absorbed Shortwave Radiation Rate",
    2521              :                             Constant::Units::W,
    2522          940 :                             state.dataHeatBal->SurfSWInAbsTotalReport(SurfLoop),
    2523              :                             OutputProcessor::TimeStepType::Zone,
    2524              :                             OutputProcessor::StoreType::Average,
    2525          940 :                             surf.Name);
    2526              :         // energy
    2527         1880 :         SetupOutputVariable(state,
    2528              :                             "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Energy",
    2529              :                             Constant::Units::J,
    2530          940 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfLoop),
    2531              :                             OutputProcessor::TimeStepType::Zone,
    2532              :                             OutputProcessor::StoreType::Sum,
    2533          940 :                             surf.Name);
    2534         1880 :         SetupOutputVariable(state,
    2535              :                             "Surface Inside Face Interior Windows Incident Beam Solar Radiation Energy",
    2536              :                             Constant::Units::J,
    2537          940 :                             state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfLoop),
    2538              :                             OutputProcessor::TimeStepType::Zone,
    2539              :                             OutputProcessor::StoreType::Sum,
    2540          940 :                             surf.Name);
    2541              :     }
    2542          141 : }
    2543              : 
    2544        71212 : void AnisoSkyViewFactors(EnergyPlusData &state)
    2545              : {
    2546              : 
    2547              :     // SUBROUTINE INFORMATION:
    2548              :     //       AUTHOR         Fred Winkelmann
    2549              :     //       DATE WRITTEN   April 1999
    2550              :     //       MODIFIED       LKL; Dec 2002 -- Anisotropic is only sky radiance option
    2551              :     //       RE-ENGINEERED  na
    2552              : 
    2553              :     // PURPOSE OF THIS SUBROUTINE:
    2554              :     // Calculates view factor multiplier, SurfAnisoSkyMult, for diffuse
    2555              :     // sky irradiance on exterior surfaces taking into account
    2556              :     // anisotropic radiance of the sky. Called by InitSurfaceHeatBalance
    2557              :     // In this case the diffuse sky irradiance on a surface is given by
    2558              :     //  SurfAnisoSkyMult(SurfNum) * DifSolarRad
    2559              :     // SurfAnisoSkyMult accounts not only for the sky radiance distribution but
    2560              :     // also for the effects of shading of sky diffuse radiation by
    2561              :     // shadowing surfaces such as overhangs. It does not account for reflection
    2562              :     // of sky diffuse radiation from shadowing surfaces.
    2563              :     // Based on an empirical model described in
    2564              :     // R. Perez, P. Ineichen, R. Seals, J. Michalsky and R. Stewart,
    2565              :     // "Modeling Daylight Availability and Irradiance Components from Direct
    2566              :     // and Global Irradiance," Solar Energy 44, 271-289, 1990.
    2567              :     // In this model the radiance of the sky consists of three distributions
    2568              :     // that are superimposed:
    2569              : 
    2570              :     // (1) An isotropic distribution that covers the entire sky dome;
    2571              :     // (2) A circumsolar brightening centered around the position of the sun;
    2572              :     // (3) A horizon brightening
    2573              :     // The circumsolar brightening is assumed to be concentrated at a point
    2574              :     // source at the center of the sun although this region actually begins at the
    2575              :     // periphery of the solar disk and falls off in intensity with increasing
    2576              :     // angular distance from the periphery.
    2577              :     // The horizon brightening is assumed to be concentrated at the horizon and
    2578              :     // to be independent of azimuth. In actuality, for clear skies, the horizon
    2579              :     // brightening is highest at the horizon and decreases in intensity away from
    2580              :     // the horizon. For overcast skies the horizon brightening has a negative value
    2581              :     // since for such skies the sky radiance increases rather than decreases away
    2582              :     // from the horizon.
    2583              :     // The F11R, F12R, etc. values were provided by R. Perez, private communication,
    2584              :     // 5/21/99. These values have higher precision than those listed in the above
    2585              :     // paper.
    2586              : 
    2587              :     // Using/Aliasing
    2588              : 
    2589              :     // Locals
    2590              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2591              :     static constexpr std::array<Real64, 7> EpsilonLimit = {
    2592              :         1.065, 1.23, 1.5, 1.95, 2.8, 4.5, 6.2}; // Upper limit of bins of the sky clearness parameter, Epsilon
    2593              :     // Circumsolar brightening coefficients; index corresponds to range of Epsilon, the sky clearness parameter
    2594              :     static constexpr std::array<Real64, 8> F11R = {-0.0083117, 0.1299457, 0.3296958, 0.5682053, 0.8730280, 1.1326077, 1.0601591, 0.6777470};
    2595              :     static constexpr std::array<Real64, 8> F12R = {0.5877285, 0.6825954, 0.4868735, 0.1874525, -0.3920403, -1.2367284, -1.5999137, -0.3272588};
    2596              :     static constexpr std::array<Real64, 8> F13R = {-0.0620636, -0.1513752, -0.2210958, -0.2951290, -0.3616149, -0.4118494, -0.3589221, -0.2504286};
    2597              :     // Horizon/zenith brightening coefficient array; index corresponds to range of Epsilon, the sky clearness parameter
    2598              :     static constexpr std::array<Real64, 8> F21R = {-0.0596012, -0.0189325, 0.0554140, 0.1088631, 0.2255647, 0.2877813, 0.2642124, 0.1561313};
    2599              :     static constexpr std::array<Real64, 8> F22R = {0.0721249, 0.0659650, -0.0639588, -0.1519229, -0.4620442, -0.8230357, -1.1272340, -1.3765031};
    2600              :     static constexpr std::array<Real64, 8> F23R = {-0.0220216, -0.0288748, -0.0260542, -0.0139754, 0.0012448, 0.0558651, 0.1310694, 0.2506212};
    2601              : 
    2602              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2603              : 
    2604              :     Real64 CosZenithAng;           // Cosine of solar zenith angle
    2605              :     Real64 ZenithAng;              // Solar zenith angle (radians)
    2606              :     Real64 ZenithAngDeg;           // Solar zenith angle (degrees)
    2607              :     Real64 F1;                     // Circumsolar brightening coefficient
    2608              :     Real64 F2;                     // Horizon/zenith brightening coefficient
    2609              :     Real64 Epsilon;                // Sky clearness parameter
    2610              :     Real64 Delta;                  // Sky brightness parameter
    2611              :     Real64 CosIncAngBeamOnSurface; // Cosine of incidence angle of beam solar on surface
    2612              :     int EpsilonBin;                // Sky clearness (Epsilon) bin index
    2613              :     Real64 AirMass;                // Relative air mass
    2614              :     Real64 AirMassH;               // Intermediate variable for relative air mass calculation
    2615              :     Real64 CircumSolarFac;         // Ratio of cosine of incidence angle to cosine of zenith angle
    2616              :     Real64 KappaZ3;                // Intermediate variable
    2617              :     Real64 ViewFactorSkyGeom;      // Geometrical sky view factor
    2618        71212 :     Real64 constexpr cosine_tolerance(0.0001);
    2619              : 
    2620        71212 :     auto &s_surf = state.dataSurface;
    2621              : 
    2622              : #ifdef EP_Count_Calls
    2623              :     ++state.dataTimingsData->NumAnisoSky_Calls;
    2624              : #endif
    2625              : 
    2626        71212 :     CosZenithAng = state.dataEnvrn->SOLCOS(3);
    2627        71212 :     ZenithAng = std::acos(CosZenithAng);
    2628        71212 :     ZenithAngDeg = ZenithAng / Constant::DegToRad;
    2629              : 
    2630        71212 :     state.dataSolarShading->SurfAnisoSkyMult = 0.0;
    2631              : 
    2632              :     //           Relative air mass
    2633        71212 :     AirMassH = (1.0 - 0.1 * state.dataEnvrn->Elevation / 1000.0);
    2634        71212 :     if (ZenithAngDeg <= 75.0) {
    2635        56901 :         AirMass = AirMassH / CosZenithAng;
    2636              :     } else {
    2637        14311 :         AirMass = AirMassH / (CosZenithAng + 0.15 * std::pow(93.9 - ZenithAngDeg, -1.253));
    2638              :     }
    2639        71212 :     KappaZ3 = 1.041 * pow_3(ZenithAng);
    2640        71212 :     Epsilon = ((state.dataEnvrn->BeamSolarRad + state.dataEnvrn->DifSolarRad) / state.dataEnvrn->DifSolarRad + KappaZ3) / (1.0 + KappaZ3);
    2641        71212 :     Delta = state.dataEnvrn->DifSolarRad * AirMass / 1353.0; // 1353 is average extraterrestrial irradiance (W/m2)
    2642              :     //           Circumsolar (F1) and horizon/zenith (F2) brightening coefficients
    2643       487897 :     for (EpsilonBin = 0; EpsilonBin < 8; ++EpsilonBin) {
    2644       487897 :         if (EpsilonBin == 7) {
    2645        27701 :             break;
    2646              :         }
    2647       460196 :         if (Epsilon < EpsilonLimit[EpsilonBin]) {
    2648        43511 :             break;
    2649              :         }
    2650              :     }
    2651        71212 :     F1 = max(0.0, F11R[EpsilonBin] + F12R[EpsilonBin] * Delta + F13R[EpsilonBin] * ZenithAng);
    2652        71212 :     F2 = F21R[EpsilonBin] + F22R[EpsilonBin] * Delta + F23R[EpsilonBin] * ZenithAng;
    2653              : 
    2654       462398 :     for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
    2655              : 
    2656       391186 :         CosIncAngBeamOnSurface = state.dataEnvrn->SOLCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
    2657       391186 :                                  state.dataEnvrn->SOLCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
    2658       391186 :                                  state.dataEnvrn->SOLCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
    2659              : 
    2660              :         // So I believe this should only be a diagnostic error...the calcs should always be within -1,+1; it's just round-off that we need to trap
    2661              :         // for
    2662       391186 :         if (CosIncAngBeamOnSurface > 1.0) {
    2663            0 :             if (CosIncAngBeamOnSurface > (1.0 + cosine_tolerance)) {
    2664            0 :                 ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too high");
    2665            0 :                 ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
    2666            0 :                 ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
    2667            0 :                 ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
    2668            0 :                 ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
    2669              :             }
    2670            0 :             CosIncAngBeamOnSurface = 1.0;
    2671       391186 :         } else if (CosIncAngBeamOnSurface < -1.0) {
    2672            0 :             if (CosIncAngBeamOnSurface < (-1.0 - cosine_tolerance)) {
    2673            0 :                 ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too low");
    2674            0 :                 ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
    2675            0 :                 ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
    2676            0 :                 ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
    2677            0 :                 ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
    2678              :             }
    2679            0 :             CosIncAngBeamOnSurface = -1.0;
    2680              :         }
    2681              : 
    2682       391186 :         ViewFactorSkyGeom = s_surf->Surface(SurfNum).ViewFactorSky;
    2683       391186 :         state.dataSolarShading->SurfMultIsoSky(SurfNum) = ViewFactorSkyGeom * (1.0 - F1);
    2684              :         //           0.0871557 below corresponds to a zenith angle of 85 deg
    2685       391186 :         CircumSolarFac = max(0.0, CosIncAngBeamOnSurface) / max(0.0871557, CosZenithAng);
    2686              :         //           For near-horizontal roofs, model has an inconsistency that gives sky diffuse
    2687              :         //           irradiance significantly different from DifSolarRad when zenith angle is
    2688              :         //           above 85 deg. The following forces irradiance to be very close to DifSolarRad
    2689              :         //           in this case.
    2690       391186 :         if (CircumSolarFac > 0.0 && CosZenithAng < 0.0871557 && s_surf->Surface(SurfNum).Tilt < 2.0) {
    2691         4187 :             CircumSolarFac = 1.0;
    2692              :         }
    2693       391186 :         state.dataSolarShading->SurfMultCircumSolar(SurfNum) = F1 * CircumSolarFac;
    2694       391186 :         state.dataSolarShading->SurfMultHorizonZenith(SurfNum) = F2 * s_surf->Surface(SurfNum).SinTilt;
    2695              : 
    2696       391186 :         if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
    2697            0 :             state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    2698       391186 :             state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
    2699       391186 :                 state.dataSolarShading->SurfMultIsoSky(SurfNum) * state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) +
    2700       391186 :                 state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
    2701       391186 :                     state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
    2702       391186 :                 state.dataSolarShading->SurfMultHorizonZenith(SurfNum) * state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
    2703              :         } else {
    2704            0 :             state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
    2705            0 :                 state.dataSolarShading->SurfMultIsoSky(SurfNum) *
    2706            0 :                     state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum) +
    2707            0 :                 state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
    2708            0 :                     state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
    2709            0 :                 state.dataSolarShading->SurfMultHorizonZenith(SurfNum) *
    2710            0 :                     state.dataSolarShading->SurfDifShdgRatioHorizHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
    2711            0 :             state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum) =
    2712            0 :                 state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
    2713              :         }
    2714       391186 :         state.dataSolarShading->SurfAnisoSkyMult(SurfNum) = max(0.0, state.dataSolarShading->SurfAnisoSkyMult(SurfNum)); // make sure not negative.
    2715        71212 :     }
    2716        71212 : }
    2717              : 
    2718           43 : void CHKBKS(EnergyPlusData &state,
    2719              :             int const NBS, // Surface Number of the potential back surface
    2720              :             int const NRS  // Surface Number of the potential shadow receiving surface
    2721              : )
    2722              : {
    2723              : 
    2724              :     // SUBROUTINE INFORMATION:
    2725              :     //       AUTHOR         Legacy Code
    2726              :     //       DATE WRITTEN
    2727              :     //       MODIFIED       Nov 2001, FW: Reverse subroutine arguments NRS and NBS to
    2728              :     //                                    correspond to how CHKBKS is called
    2729              :     //                      Jan 2002, FW: change error message
    2730              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    2731              :     //       Sep 2020: Revised the vector computation method to reliably produce CVec,
    2732              :     //                 and simplified the warning messages.
    2733              : 
    2734              :     // PURPOSE OF THIS SUBROUTINE:
    2735              :     // Determines whether a any vertices of the back surface are in front of the receiving surface;
    2736              :     // if so, gives severe error.  Only base heat transfer surfaces are checked.
    2737              : 
    2738              :     // METHODOLOGY EMPLOYED:
    2739              :     // na
    2740              : 
    2741              :     // REFERENCES:
    2742              :     // BLAST/IBLAST code, original author George Walton
    2743              : 
    2744              :     // Using/Aliasing
    2745              :     using namespace Vectors;
    2746              : 
    2747              :     int N;       // Loop Control (vertex counter)
    2748              :     int NVRS;    // Number of vertices of the receiving surface
    2749              :     int NVBS;    // Number of vertices of the back surface
    2750              :     Real64 DOTP; // Dot product of C and D
    2751              : 
    2752              :     // Object Data
    2753           43 :     Vector CVec(0.0); // Vector perpendicular to surface at vertex 1
    2754           43 :     Vector DVec(0.0); // Vector from vertex 1 of first surface to vertex 'n' of second surface
    2755              : 
    2756           43 :     auto &s_surf = state.dataSurface;
    2757              : 
    2758           43 :     NVRS = s_surf->Surface(NRS).Sides;
    2759           43 :     NVBS = s_surf->Surface(NBS).Sides;
    2760              : 
    2761              :     // SEE IF ANY VERTICES OF THE back surface ARE IN FRONT OF THE receiving surface
    2762              : 
    2763          133 :     for (N = 2; N < NVRS; N++) {
    2764          180 :         CVec += cross(s_surf->Surface(NRS).Vertex(N) - s_surf->Surface(NRS).Vertex(1),
    2765          270 :                       s_surf->Surface(NRS).Vertex((N + 1)) - s_surf->Surface(NRS).Vertex(1));
    2766              :     }
    2767           43 :     CVec /= (NVRS >= 3 ? NVRS : 3);
    2768              : 
    2769          171 :     for (N = 1; N <= NVBS; ++N) {
    2770          144 :         DVec = s_surf->Surface(NBS).Vertex(N) - s_surf->Surface(NRS).Vertex(1);
    2771          144 :         DOTP = dot(CVec, DVec);
    2772          144 :         if (DOTP > 0.0009) {
    2773           32 :             ShowSevereError(state, "Problem in interior solar distribution calculation (CHKBKS)");
    2774           16 :             ShowContinueError(state, format("   Solar Distribution = FullInteriorExterior will not work in Zone={}", s_surf->Surface(NRS).ZoneName));
    2775           32 :             ShowContinueError(state,
    2776           32 :                               format("   because one or more of vertices, such as Vertex {} of back surface={}, is in front of receiving surface={}",
    2777              :                                      N,
    2778           16 :                                      s_surf->Surface(NBS).Name,
    2779           16 :                                      s_surf->Surface(NRS).Name));
    2780           16 :             ShowContinueError(state, format("   (Dot Product indicator={:20.4F})", DOTP));
    2781           32 :             ShowContinueError(state,
    2782              :                               "   Check surface geometry; if OK, use Solar Distribution = FullExterior instead. Use Output:Diagnostics, "
    2783              :                               "DisplayExtraWarnings; for more details.");
    2784           16 :             if (!state.dataGlobal->DisplayExtraWarnings) {
    2785           16 :                 break;
    2786              :             }
    2787              :         }
    2788              :     }
    2789           43 : }
    2790              : 
    2791         2566 : void CHKGSS(EnergyPlusData &state,
    2792              :             int const NRS,     // Surface number of the potential shadow receiving surface
    2793              :             int const NSS,     // Surface number of the potential shadow casting surface
    2794              :             Real64 const ZMIN, // Lowest point of the receiving surface
    2795              :             bool &CannotShade  // TRUE if shadow casting surface cannot shade receiving surface.
    2796              : )
    2797              : {
    2798              : 
    2799              :     // SUBROUTINE INFORMATION:
    2800              :     //       AUTHOR         Legacy Code
    2801              :     //       DATE WRITTEN
    2802              :     //       MODIFIED       na
    2803              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    2804              : 
    2805              :     // PURPOSE OF THIS SUBROUTINE:
    2806              :     // Determines the possible shadowing combinations.  The
    2807              :     // routine checks detached shadowing or base heat transfer surfaces
    2808              :     // for the possibility that they cannot shade a given base heat transfer surface.
    2809              : 
    2810              :     // METHODOLOGY EMPLOYED:
    2811              :     // Shadowing is not possible if:
    2812              :     // 1.  The lowest point of the shadow receiving surface (receiving surface)
    2813              :     //     Is higher than the highest point of the shadow casting surface (s.s.)
    2814              :     // 2.  The shadow casting surface Faces up (e.g. A flat roof)
    2815              :     // 3.  The shadow casting surface Is behind the receiving surface
    2816              :     // 4.  The receiving surface is behind the shadow casting surface
    2817              : 
    2818              :     // REFERENCES:
    2819              :     // BLAST/IBLAST code, original author George Walton
    2820              : 
    2821              :     // Using/Aliasing
    2822              :     using namespace Vectors;
    2823              : 
    2824              :     // Object Data
    2825              : 
    2826         2566 :     CannotShade = true;
    2827              : 
    2828         2566 :     auto &s_surf = state.dataSurface;
    2829              : 
    2830              :     // see if no point of shadow casting surface is above low point of receiving surface
    2831              : 
    2832         2566 :     auto const &surface_C = s_surf->Surface(NSS);
    2833         2566 :     if (surface_C.OutNormVec(3) > 0.9999) {
    2834         1198 :         return; // Shadow Casting Surface is horizontal and facing upward
    2835              :     }
    2836         2062 :     auto const &vertex_C = surface_C.Vertex;
    2837         2062 :     Real64 ZMAX(vertex_C(1).z);
    2838         8282 :     for (int i = 2, e = surface_C.Sides; i <= e; ++i) {
    2839         6220 :         ZMAX = std::max(ZMAX, vertex_C(i).z);
    2840              :     }
    2841         2062 :     if (ZMAX <= ZMIN) {
    2842          694 :         return;
    2843              :     }
    2844              : 
    2845              :     // SEE IF ANY VERTICES OF THE Shadow Casting Surface ARE ABOVE THE PLANE OF THE receiving surface
    2846              : 
    2847         1368 :     auto const &surface_R = s_surf->Surface(NRS);
    2848         1368 :     auto const &vertex_R = surface_R.Vertex;
    2849         1368 :     Vector const &vertex_R_2 = vertex_R(2);
    2850         1368 :     Vector const AVec = (vertex_R(1) - vertex_R_2); // Vector from vertex 2 to vertex 1 of receiving surface
    2851         1368 :     Vector const BVec = (vertex_R(3) - vertex_R_2); // Vector from vertex 2 to vertex 3 of receiving surface
    2852              : 
    2853         1368 :     Vector const CVec = cross(BVec, AVec); // Vector perpendicular to surface at vertex 2
    2854              : 
    2855         1368 :     int const NVSS = surface_C.Sides; // Number of vertices of the shadow casting surface
    2856         1368 :     Real64 DOTP(0.0);                 // Dot Product
    2857         5725 :     for (int I = 1; I <= NVSS; ++I) {
    2858         4662 :         DOTP = dot(CVec, vertex_C(I) - vertex_R_2);
    2859         4662 :         if (DOTP > state.dataSolarShading->TolValue) {
    2860          305 :             break; // DO loop
    2861              :         }
    2862              :     }
    2863              : 
    2864              :     // SEE IF ANY VERTICES OF THE receiving surface ARE ABOVE THE PLANE OF THE S.S.
    2865              : 
    2866         1368 :     if (DOTP > state.dataSolarShading->TolValue) {
    2867              : 
    2868          305 :         Vector const &vertex_C_2 = vertex_C(2);
    2869          305 :         Vector const AVec(vertex_C(1) - vertex_C_2);
    2870          305 :         Vector const BVec(vertex_C(3) - vertex_C_2);
    2871              : 
    2872          305 :         Vector const CVec(cross(BVec, AVec));
    2873              : 
    2874          305 :         int const NVRS = surface_R.Sides; // Number of vertices of the receiving surface
    2875         1097 :         for (int I = 1; I <= NVRS; ++I) {
    2876          918 :             DOTP = dot(CVec, vertex_R(I) - vertex_C_2);
    2877          918 :             if (DOTP > state.dataSolarShading->TolValue) {
    2878          126 :                 CannotShade = false;
    2879          126 :                 break; // DO loop
    2880              :             }
    2881              :         }
    2882          305 :     }
    2883         1368 : }
    2884              : 
    2885           70 : void CHKSBS(EnergyPlusData &state,
    2886              :             int const HTS,   // Heat transfer surface number of the general receiving surf
    2887              :             int const GRSNR, // Surface number of general receiving surface
    2888              :             int const SBSNR  // Surface number of subsurface
    2889              : )
    2890              : {
    2891              : 
    2892              :     // SUBROUTINE INFORMATION:
    2893              :     //       AUTHOR         Legacy Code
    2894              :     //       DATE WRITTEN
    2895              :     //       MODIFIED       na
    2896              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    2897              : 
    2898              :     // PURPOSE OF THIS SUBROUTINE:
    2899              :     // Checks that a subsurface is completely
    2900              :     // enclosed by its base surface.
    2901              : 
    2902              :     // REFERENCES:
    2903              :     // BLAST/IBLAST code, original author George Walton
    2904              : 
    2905              :     // 3D Planar Polygons
    2906              :     // In 3D applications, one sometimes wants to test a point and polygon that are in the same plane.
    2907              :     // For example, one may have the intersection point of a ray with the plane of a polyhedron's face,
    2908              :     // and want to test if it is inside the face.  Or one may want to know if the base of a 3D perpendicular
    2909              :     // dropped from a point is inside a planar polygon.
    2910              : 
    2911              :     // 3D inclusion is easily determined by projecting the point and polygon into 2D.  To do this, one simply
    2912              :     // ignores one of the 3D coordinates and uses the other two.  To optimally select the coordinate to ignore,
    2913              :     // compute a normal vector to the plane, and select the coordinate with the largest absolute value [Snyder & Barr, 1987].
    2914              :     // This gives the projection of the polygon with maximum area, and results in robust computations.
    2915              :     // John M. Snyder & Alan H. Barr, "Ray Tracing Complex Models Containing Surface Tessellations",
    2916              :     // Computer Graphics 21(4), 119-126 (1987) [also in the Proceedings of SIGGRAPH 1987]
    2917              :     //--- using adapted routine from Triangulation code -- EnergyPlus.
    2918              : 
    2919              :     // MSG - for error message
    2920           70 :     static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
    2921              : 
    2922              :     int N;   // Loop Control
    2923              :     int NVT; // Number of vertices
    2924              :     int NS1; // Number of the figure being overlapped
    2925              :     int NS2; // Number of the figure doing overlapping
    2926              :     int NS3; // Location to place results of overlap
    2927              : 
    2928              :     bool inside;
    2929              : 
    2930              :     bool Out;
    2931              :     Real64 X1; // ,SX,SY,SZ
    2932              :     Real64 Y1;
    2933              :     Real64 Z1;
    2934              :     Real64 X2;
    2935              :     Real64 Y2;
    2936              :     Real64 Z2;
    2937              :     Real64 BX;
    2938              :     Real64 BY;
    2939              :     Real64 BZ;
    2940              :     Real64 BMAX;
    2941              :     //  INTEGER M
    2942              : 
    2943           70 :     auto &s_surf = state.dataSurface;
    2944              : 
    2945           70 :     if (state.dataSolarShading->CHKSBSOneTimeFlag) {
    2946           33 :         state.dataSolarShading->XVT.allocate(s_surf->MaxVerticesPerSurface + 1);
    2947           33 :         state.dataSolarShading->YVT.allocate(s_surf->MaxVerticesPerSurface + 1);
    2948           33 :         state.dataSolarShading->ZVT.allocate(s_surf->MaxVerticesPerSurface + 1);
    2949           33 :         state.dataSolarShading->XVT = 0.0;
    2950           33 :         state.dataSolarShading->YVT = 0.0;
    2951           33 :         state.dataSolarShading->ZVT = 0.0;
    2952           33 :         state.dataSolarShading->CHKSBSOneTimeFlag = false;
    2953              :     }
    2954              : 
    2955           70 :     NS1 = 1;
    2956           70 :     NS2 = 2;
    2957           70 :     NS3 = 3;
    2958           70 :     state.dataSolarShading->HCT(1) = 0.0;
    2959           70 :     state.dataSolarShading->HCT(2) = 0.0;
    2960              : 
    2961              :     // Put coordinates of base surface into clockwise sequence on the x'-y' plane.
    2962              : 
    2963           70 :     state.dataSolarShading->XVT = 0.0;
    2964           70 :     state.dataSolarShading->YVT = 0.0;
    2965           70 :     state.dataSolarShading->ZVT = 0.0;
    2966           70 :     state.dataSolarShading->XVS = 0.0;
    2967           70 :     state.dataSolarShading->YVS = 0.0;
    2968           70 :     CTRANS(state, GRSNR, HTS, NVT, state.dataSolarShading->XVT, state.dataSolarShading->YVT, state.dataSolarShading->ZVT);
    2969          350 :     for (N = 1; N <= NVT; ++N) {
    2970          280 :         state.dataSolarShading->XVS(N) = state.dataSolarShading->XVT(NVT + 1 - N);
    2971          280 :         state.dataSolarShading->YVS(N) = state.dataSolarShading->YVT(NVT + 1 - N);
    2972              :     }
    2973              : 
    2974           70 :     HTRANS1(state, NS2, NVT);
    2975              : 
    2976              :     // Put coordinates of the subsurface into clockwise sequence.
    2977              : 
    2978           70 :     state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
    2979          350 :     for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
    2980          280 :         state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
    2981          280 :         state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
    2982              :     }
    2983           70 :     HTRANS1(state, NS1, state.dataSolarShading->NVS);
    2984              : 
    2985              :     // Determine the overlap condition.
    2986              : 
    2987           70 :     DeterminePolygonOverlap(state, NS1, NS2, NS3);
    2988              : 
    2989              :     // Print error condition if necessary.
    2990              : 
    2991           70 :     if (state.dataSolarShading->OverlapStatus != FirstSurfWithinSecond) {
    2992            0 :         Out = false;
    2993              :         // C                            COMPUTE COMPONENTS OF VECTOR
    2994              :         // C                            NORMAL TO BASE SURFACE.
    2995            0 :         X1 = s_surf->Surface(GRSNR).Vertex(1).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(1,GRSNR)-XV(2,GRSNR)
    2996            0 :         Y1 = s_surf->Surface(GRSNR).Vertex(1).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(1,GRSNR)-YV(2,GRSNR)
    2997            0 :         Z1 = s_surf->Surface(GRSNR).Vertex(1).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(1,GRSNR)-ZV(2,GRSNR)
    2998            0 :         X2 = s_surf->Surface(GRSNR).Vertex(3).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(3,GRSNR)-XV(2,GRSNR)
    2999            0 :         Y2 = s_surf->Surface(GRSNR).Vertex(3).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(3,GRSNR)-YV(2,GRSNR)
    3000            0 :         Z2 = s_surf->Surface(GRSNR).Vertex(3).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(3,GRSNR)-ZV(2,GRSNR)
    3001            0 :         BX = Y1 * Z2 - Y2 * Z1;
    3002            0 :         BY = Z1 * X2 - Z2 * X1;
    3003            0 :         BZ = X1 * Y2 - X2 * Y1;
    3004              :         // C                            FIND LARGEST COMPONENT.
    3005            0 :         BMAX = max(std::abs(BX), std::abs(BY), std::abs(BZ));
    3006              :         // C
    3007            0 :         if (std::abs(BX) == BMAX) {
    3008              :             //        write(outputfiledebug,*) ' looking bx-bmax',bmax
    3009            0 :             for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
    3010            0 :                 inside = polygon_contains_point(
    3011            0 :                     s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), true, false, false);
    3012            0 :                 if (!inside) {
    3013            0 :                     Out = true;
    3014              :                     //            do m=1,surface(grsnr)%sides
    3015              :                     //            write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
    3016              :                     //            write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
    3017              :                     //            enddo
    3018              :                     //            EXIT
    3019              :                 }
    3020              :                 //          Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
    3021              :                 //          Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
    3022              :                 //          DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
    3023              :                 //            Y2 = Y1
    3024              :                 //            Z2 = Z1
    3025              :                 //            Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
    3026              :                 //            Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
    3027              :                 //            SX = Y1*Z2-Y2*Z1
    3028              :                 //            IF(SX*BX.LT.-1.0d-6) THEN
    3029              :                 //              OUT=.TRUE.
    3030              :                 //              write(outputfiledebug,*) 'sx*bx=',sx*bx
    3031              :                 //              write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
    3032              :                 //              write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
    3033              :                 //            endif
    3034              :                 //          ENDDO
    3035              :                 //          IF (OUT) EXIT
    3036              :             }
    3037            0 :         } else if (std::abs(BY) == BMAX) {
    3038              :             //        write(outputfiledebug,*) ' looking by-bmax',bmax
    3039            0 :             for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
    3040            0 :                 inside = polygon_contains_point(
    3041            0 :                     s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, true, false);
    3042            0 :                 if (!inside) {
    3043            0 :                     Out = true;
    3044              :                     //            do m=1,surface(grsnr)%sides
    3045              :                     //            write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
    3046              :                     //            write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
    3047              :                     //            enddo
    3048              :                     //            EXIT
    3049              :                 }
    3050              :                 //          Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
    3051              :                 //          X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
    3052              :                 //          DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
    3053              :                 //            Z2 = Z1
    3054              :                 //            X2 = X1
    3055              :                 //            Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
    3056              :                 //            X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
    3057              :                 //            SY = Z1*X2-Z2*X1
    3058              :                 //            IF(SY*BY.LT.-1.0d-6) THEN
    3059              :                 //              OUT=.TRUE.
    3060              :                 //              write(outputfiledebug,*) 'sy*by=',sy*by
    3061              :                 //              write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
    3062              :                 //              write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
    3063              :                 //            ENDIF
    3064              :                 //          ENDDO
    3065              :                 //          IF (OUT) EXIT
    3066              :             }
    3067              :         } else {
    3068              :             //        write(outputfiledebug,*) ' looking bz-bmax',bmax
    3069            0 :             for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
    3070            0 :                 inside = polygon_contains_point(
    3071            0 :                     s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, false, true);
    3072            0 :                 if (!inside) {
    3073            0 :                     Out = true;
    3074              :                     //            do m=1,surface(grsnr)%sides
    3075              :                     //            write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
    3076              :                     //            write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
    3077              :                     //            enddo
    3078              :                     //            EXIT
    3079              :                 }
    3080              :                 //          X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
    3081              :                 //          Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
    3082              :                 //          DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
    3083              :                 //            X2 = X1
    3084              :                 //            Y2 = Y1
    3085              :                 //            X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
    3086              :                 //            Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
    3087              :                 //            SZ = X1*Y2-X2*Y1
    3088              :                 //            IF(SZ*BZ.LT.-1.0d-6) THEN
    3089              :                 //              OUT=.TRUE.
    3090              :                 //              write(outputfiledebug,*) 'sz*bz=',sz*bz
    3091              :                 //              write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
    3092              :                 //              write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
    3093              :                 //            ENDIF
    3094              :                 //          ENDDO
    3095              :                 //          IF (OUT) EXIT
    3096              :             }
    3097              :         }
    3098              :         //    CALL ShowWarningError(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='//  &
    3099              :         //                           TRIM(cOverLapStatus(OverlapStatus)))
    3100              :         //    CALL ShowContinueError(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))//  &
    3101              :         //                     ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"')
    3102              :         //    IF (FirstSurroundError) THEN
    3103              :         //      CALL ShowWarningError(state, 'Base Surface does not surround subsurface errors occurring...'//  &
    3104              :         //                     'Check that the SurfaceGeometry object is expressing the proper starting corner and '//  &
    3105              :         //                     'direction [CounterClockwise/Clockwise]')
    3106              :         //      FirstSurroundError=.FALSE.
    3107              :         //    ENDIF
    3108            0 :         if (Out) {
    3109            0 :             state.dataSolarShading->TrackBaseSubSurround.redimension(++state.dataSolarShading->NumBaseSubSurround);
    3110            0 :             state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex1 = GRSNR;
    3111            0 :             state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex2 = SBSNR;
    3112            0 :             state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).MiscIndex =
    3113            0 :                 state.dataSolarShading->OverlapStatus;
    3114              :             //    CALL ShowRecurringWarningErrorAtEnd(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='//  &
    3115              :             //                       TRIM(cOverLapStatus(OverlapStatus)), &
    3116              :             //                       TrackBaseSubSurround(GRSNR)%ErrIndex1)
    3117              :             //    CALL ShowRecurringContinueErrorAtEnd(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))//  &
    3118              :             //                       ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"',  &
    3119              :             //                      TrackBaseSubSurround(SBSNR)%ErrIndex2)
    3120            0 :             if (state.dataSolarShading->shd_stream) {
    3121            0 :                 *state.dataSolarShading->shd_stream << "==== Base does not Surround subsurface details ====\n";
    3122            0 :                 *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(GRSNR).Name << ' '
    3123            0 :                                                     << state.dataSolarShading->cOverLapStatus(state.dataSolarShading->OverlapStatus) << '\n';
    3124            0 :                 *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << GRSNR << " NSides=" << std::setw(5)
    3125            0 :                                                     << s_surf->Surface(GRSNR).Sides << '\n';
    3126            0 :                 *state.dataSolarShading->shd_stream << std::fixed << std::setprecision(2);
    3127            0 :                 for (N = 1; N <= s_surf->Surface(GRSNR).Sides; ++N) {
    3128            0 :                     Vector const &v(s_surf->Surface(GRSNR).Vertex(N));
    3129            0 :                     *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
    3130            0 :                                                         << v.y << ',' << std::setw(15) << v.z << ")\n";
    3131              :                 }
    3132            0 :                 *state.dataSolarShading->shd_stream << "SubSurface=" << s_surf->Surface(SBSNR).Name << '\n';
    3133            0 :                 *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << SBSNR << " NSides=" << std::setw(5)
    3134            0 :                                                     << s_surf->Surface(SBSNR).Sides << '\n';
    3135            0 :                 for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) {
    3136            0 :                     Vector const &v(s_surf->Surface(SBSNR).Vertex(N));
    3137            0 :                     *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
    3138            0 :                                                         << v.y << ',' << std::setw(15) << v.z << ")\n";
    3139              :                 }
    3140            0 :                 *state.dataSolarShading->shd_stream << "================================\n";
    3141              :             }
    3142              :         }
    3143              :     }
    3144           70 : }
    3145              : 
    3146            6 : bool polygon_contains_point(int const nsides,            // number of sides (vertices)
    3147              :                             Array1D<Vector> &polygon_3d, // points of polygon
    3148              :                             Vector const &point_3d,      // point to be tested
    3149              :                             bool const ignorex,
    3150              :                             bool const ignorey,
    3151              :                             bool const ignorez)
    3152              : {
    3153              : 
    3154              :     // Function information:
    3155              :     //       Author         Linda Lawrie
    3156              :     //       Date written   October 2005
    3157              :     //       Modified       na
    3158              :     //       Re-engineered  na
    3159              : 
    3160              :     // Purpose of this function:
    3161              :     // Determine if a point is inside a simple 2d polygon.  For a simple polygon (one whose
    3162              :     // boundary never crosses itself).  The polygon does not need to be convex.
    3163              : 
    3164              :     // References:
    3165              :     // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
    3166              :     // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
    3167              : 
    3168              :     // Use statements:
    3169              :     // Using/Aliasing
    3170              :     using namespace DataVectorTypes;
    3171              : 
    3172              :     // return value, true=inside, false = not inside
    3173              : 
    3174            6 :     EP_SIZE_CHECK(polygon_3d, nsides);
    3175              : 
    3176              :     int ip1;
    3177              : 
    3178              :     // Object Data
    3179            6 :     Array1D<Vector_2d> polygon(nsides);
    3180            6 :     Vector_2d point;
    3181              : 
    3182            6 :     bool inside = false;
    3183            6 :     if (ignorex) {
    3184           10 :         for (int i = 1; i <= nsides; ++i) {
    3185            8 :             polygon(i).x = polygon_3d(i).y;
    3186            8 :             polygon(i).y = polygon_3d(i).z;
    3187              :         }
    3188            2 :         point.x = point_3d.y;
    3189            2 :         point.y = point_3d.z;
    3190            4 :     } else if (ignorey) {
    3191           10 :         for (int i = 1; i <= nsides; ++i) {
    3192            8 :             polygon(i).x = polygon_3d(i).x;
    3193            8 :             polygon(i).y = polygon_3d(i).z;
    3194              :         }
    3195            2 :         point.x = point_3d.x;
    3196            2 :         point.y = point_3d.z;
    3197            2 :     } else if (ignorez) {
    3198           10 :         for (int i = 1; i <= nsides; ++i) {
    3199            8 :             polygon(i).x = polygon_3d(i).x;
    3200            8 :             polygon(i).y = polygon_3d(i).y;
    3201              :         }
    3202            2 :         point.x = point_3d.x;
    3203            2 :         point.y = point_3d.y;
    3204              :     } else { // Illegal
    3205            0 :         assert(false);
    3206              :         point.x = point.y = 0.0; // Elim possibly used uninitialized warnings
    3207              :     }
    3208              : 
    3209           30 :     for (int i = 1; i <= nsides; ++i) {
    3210              : 
    3211           24 :         if (i < nsides) {
    3212           18 :             ip1 = i + 1;
    3213              :         } else {
    3214            6 :             ip1 = 1;
    3215              :         }
    3216              : 
    3217           24 :         if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
    3218            6 :             if ((point.x - polygon(i).x) - (point.y - polygon(i).y) * (polygon(ip1).x - polygon(i).x) / (polygon(ip1).y - polygon(i).y) < 0) {
    3219            3 :                 inside = !inside;
    3220              :             }
    3221              :         }
    3222              :     }
    3223              : 
    3224            6 :     return inside;
    3225            6 : }
    3226              : 
    3227          104 : void ComputeIntSolarAbsorpFactors(EnergyPlusData &state)
    3228              : {
    3229              : 
    3230              :     // SUBROUTINE INFORMATION:
    3231              :     //       AUTHOR         Legacy Code
    3232              :     //       MODIFIED       B. Griffith, Oct 2010, deal with no floor case
    3233              :     //                      L. Lawrie, Mar 2012, relax >154 tilt even further (>120 considered non-wall by ASHRAE)
    3234              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3235              : 
    3236              :     // PURPOSE OF THIS SUBROUTINE:
    3237              :     // This routine computes the fractions of diffusely transmitted
    3238              :     // solar energy absorbed by each zone surface.
    3239              : 
    3240              :     // METHODOLOGY EMPLOYED:
    3241              :     // It is assumed that all transmitted solar energy is incident
    3242              :     // on the floors of the zone (or enclosure).  The fraction directly absorbed in
    3243              :     // the floor is given by 'ISABSF'.  It is proportional to the
    3244              :     // area * solar absorptance.  The remaining solar energy is then
    3245              :     // distributed uniformly around the room according to
    3246              :     // area*absorptance product
    3247              : 
    3248              :     // REFERENCES:
    3249              :     // BLAST/IBLAST code, original author George Walton
    3250              : 
    3251              :     using namespace DataWindowEquivalentLayer;
    3252              : 
    3253              :     Real64 AreaSum;       // Intermediate calculation value
    3254              :     int Lay;              // Window glass layer number
    3255              :     Real64 AbsDiffTotWin; // Sum of a window's glass layer solar absorptances
    3256              :     Real64 TestFractSum;
    3257              :     Real64 HorizAreaSum;
    3258              : 
    3259          104 :     auto &s_surf = state.dataSurface;
    3260              : 
    3261          235 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    3262          131 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
    3263              : 
    3264          131 :         AreaSum = 0.0;
    3265          131 :         TestFractSum = 0.0;
    3266          841 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    3267          710 :             if (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone && s_surf->Surface(SurfNum).CosTilt < -0.5) {
    3268          144 :                 AreaSum += s_surf->Surface(SurfNum).Area;
    3269              :             }
    3270              :         }
    3271              : 
    3272          131 :         HorizAreaSum = AreaSum;
    3273              : 
    3274          131 :         if ((thisEnclosure.FloorArea <= 0.0) && (HorizAreaSum > 0.0)) {
    3275              :             // fill floor area even though surfs not called "Floor", they are roughly horizontal and face upwards.
    3276            0 :             thisEnclosure.FloorArea = HorizAreaSum;
    3277            0 :             ShowWarningError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
    3278            0 :             ShowContinueError(state, format("...Enclosure=\"{}\" has no floor, but has approximate horizontal surfaces.", thisEnclosure.Name));
    3279            0 :             ShowContinueError(state, format("...these Tilt > 120 degrees, (area=[{:.2R}] m2) will be used.", HorizAreaSum));
    3280              :         }
    3281              : 
    3282              :         // Compute ISABSF
    3283              : 
    3284          841 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    3285              : 
    3286              :             // only horizontal surfaces. !      !CR 8229, relaxed from -0.99 to -0.5  (Tilt > 154)
    3287              :             // only horizontal surfaces. !      !CR8769 use ASHRAE std of >120, -0.9 to -0.5  (Tilt > 120)
    3288          854 :             if ((state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType != StandardZone || s_surf->Surface(SurfNum).CosTilt < -0.5) &&
    3289          144 :                 (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone || s_surf->Surface(SurfNum).ExtBoundCond > 0)) {
    3290              : 
    3291          144 :                 int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    3292          144 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    3293              :                 // last minute V3.1
    3294          144 :                 if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
    3295          142 :                     if (AreaSum > 0.0) {
    3296          142 :                         state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
    3297              :                     }
    3298              :                 } else { // Window (floor windows are assumed to have no shading device and no divider,
    3299              :                     // and assumed to be non-switchable)
    3300            2 :                     AbsDiffTotWin = 0.0;
    3301            2 :                     if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
    3302            6 :                         for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
    3303            4 :                             AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
    3304              :                         }
    3305              :                     } else {
    3306            0 :                         for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
    3307            0 :                             AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
    3308              :                         }
    3309              :                     }
    3310            2 :                     if (AreaSum > 0.0) {
    3311            2 :                         state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
    3312              :                     }
    3313              :                 }
    3314              :             }
    3315              :             // CR 8229  test ISABSF for problems
    3316          710 :             TestFractSum += state.dataSolarShading->SurfIntAbsFac(SurfNum);
    3317              :         }
    3318              : 
    3319          131 :         if (TestFractSum <= 0.0) {
    3320            9 :             if (thisEnclosure.ExtWindowArea > 0.0) { // we have a problem, the sun has no floor to go to
    3321            3 :                 if (thisEnclosure.FloorArea <= 0.0) {
    3322            0 :                     ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
    3323            0 :                     ShowContinueError(state, format("but Zone or Enclosure =\"{}\" does not appear to have any floor surfaces.", thisEnclosure.Name));
    3324            0 :                     ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
    3325              :                 } else { // Floor Area > 0 but still can't absorb
    3326            6 :                     ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
    3327            3 :                     ShowContinueError(state, format("but Zone or Enclosure =\"{}\" floor cannot absorb any solar gains. ", thisEnclosure.Name));
    3328            6 :                     ShowContinueError(state, "Check the solar absorptance of the inside layer of the floor surface construction/material.");
    3329            9 :                     ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
    3330              :                 }
    3331              : 
    3332              :                 // try again but use an even spread across all the surfaces in the zone, regardless of horizontal
    3333              :                 //  so as to not lose solar energy
    3334            3 :                 AreaSum = 0.0;
    3335            3 :                 for (int SurfNum : thisEnclosure.SurfacePtr) {
    3336            0 :                     AreaSum += s_surf->Surface(SurfNum).Area;
    3337              :                 }
    3338              : 
    3339            3 :                 for (int const SurfNum : thisEnclosure.SurfacePtr) {
    3340            0 :                     int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    3341            0 :                     auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    3342            0 :                     if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
    3343            0 :                         if (AreaSum > 0.0) {
    3344            0 :                             state.dataSolarShading->SurfIntAbsFac(SurfNum) =
    3345            0 :                                 s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
    3346              :                         }
    3347              :                     } else { // Window (floor windows are assumed to have no shading device and no divider,
    3348              :                         // and assumed to be non-switchable)
    3349            0 :                         AbsDiffTotWin = 0.0;
    3350            0 :                         if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
    3351            0 :                             for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
    3352            0 :                                 AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
    3353              :                             }
    3354              :                         } else {
    3355            0 :                             for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
    3356            0 :                                 AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
    3357              :                             }
    3358              :                         }
    3359              : 
    3360            0 :                         if (AreaSum > 0.0) {
    3361            0 :                             state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
    3362              :                         }
    3363              :                     }
    3364              :                 }
    3365              :             }
    3366              :         }
    3367              : 
    3368              :     } // enclosure loop
    3369          104 : }
    3370              : 
    3371        11826 : void CLIP(EnergyPlusData &state, int const NVT, Array1D<Real64> &XVT, Array1D<Real64> &YVT, Array1D<Real64> &ZVT)
    3372              : {
    3373              : 
    3374              :     // SUBROUTINE INFORMATION:
    3375              :     //       AUTHOR         Legacy Code
    3376              :     //       DATE WRITTEN
    3377              :     //       MODIFIED       na
    3378              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3379              : 
    3380              :     // PURPOSE OF THIS SUBROUTINE:
    3381              :     // This subroutine 'clips' the shadow casting surface polygon so that
    3382              :     // none of it lies below the plane of the receiving surface polygon.  This
    3383              :     // prevents the casting of 'false' shadows.
    3384              : 
    3385              :     // REFERENCES:
    3386              :     // BLAST/IBLAST code, original author George Walton
    3387              : 
    3388        11826 :     int NABOVE(0);    // Number of vertices of shadow casting surface. above the plane of receiving surface
    3389        11826 :     int NEXT(0);      // First vertex above plane of receiving surface
    3390        11826 :     int NON(0);       // Number of vertices of shadow casting surface. on plane of receiving surface
    3391        11826 :     Real64 XIN(0.0);  // X of entry point of shadow casting surface. into plane of receiving surface
    3392        11826 :     Real64 XOUT(0.0); // X of exit point of shadow casting surface. from plane of receiving surface
    3393        11826 :     Real64 YIN(0.0);  // Y of entry point of shadow casting surface. into plane of receiving surface
    3394        11826 :     Real64 YOUT(0.0); // Y of exit point of shadow casting surface. from plane of receiving surface
    3395              :     //  INTEGER NVS      ! Number of vertices of the shadow/clipped surface
    3396              : 
    3397              :     // Determine if the shadow casting surface. is above, below, or intersects with the plane of the receiving surface
    3398              : 
    3399        11826 :     state.dataSolarShading->NumVertInShadowOrClippedSurface = state.dataSolarShading->NVS;
    3400        59098 :     for (int N = 1; N <= NVT; ++N) {
    3401        47272 :         Real64 const ZVT_N(ZVT(N));
    3402        47272 :         if (ZVT_N > 0.0) {
    3403        33104 :             ++NABOVE;
    3404        14168 :         } else if (ZVT_N == 0.0) {
    3405         6998 :             ++NON;
    3406              :         }
    3407              :     }
    3408              : 
    3409        11826 :     if (NABOVE + NON == NVT) { // Rename the unclipped shadow casting surface.
    3410              : 
    3411         8241 :         state.dataSolarShading->NVS = NVT;
    3412         8241 :         state.dataSolarShading->NumVertInShadowOrClippedSurface = NVT;
    3413        41173 :         for (int N = 1; N <= NVT; ++N) {
    3414        32932 :             state.dataSolarShading->XVC(N) = XVT(N);
    3415        32932 :             state.dataSolarShading->YVC(N) = YVT(N);
    3416        32932 :             state.dataSolarShading->ZVC(N) = ZVT(N);
    3417              :         }
    3418              : 
    3419         3585 :     } else if (NABOVE == 0) { // Totally submerged shadow casting surface.
    3420              : 
    3421            0 :         state.dataSolarShading->NVS = 0;
    3422            0 :         state.dataSolarShading->NumVertInShadowOrClippedSurface = 0;
    3423              : 
    3424              :     } else { // Remove (clip) that portion of the shadow casting surface. which is below the receiving surface
    3425              : 
    3426         3585 :         state.dataSolarShading->NVS = NABOVE + 2;
    3427         3585 :         state.dataSolarShading->NumVertInShadowOrClippedSurface = NABOVE + 2;
    3428         3585 :         Real64 ZVT_N, ZVT_P(ZVT(1));
    3429         3585 :         XVT(NVT + 1) = XVT(1);
    3430         3585 :         YVT(NVT + 1) = YVT(1);
    3431         3585 :         ZVT(NVT + 1) = ZVT_P;
    3432        17925 :         for (int N = 1, P = 2; N <= NVT; ++N, ++P) {
    3433        14340 :             ZVT_N = ZVT_P;
    3434        14340 :             ZVT_P = ZVT(P);
    3435        14340 :             if (ZVT_N >= 0.0 && ZVT_P < 0.0) { // Line enters plane of receiving surface
    3436         3585 :                 Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
    3437         3585 :                 XIN = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
    3438         3585 :                 YIN = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
    3439        14340 :             } else if (ZVT_N <= 0.0 && ZVT_P > 0.0) { // Line exits plane of receiving surface
    3440         3585 :                 NEXT = N + 1;
    3441         3585 :                 Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
    3442         3585 :                 XOUT = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
    3443         3585 :                 YOUT = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
    3444              :             }
    3445              :         }
    3446              : 
    3447              :         // Renumber the vertices of the clipped shadow casting surface. so they are still counter-clockwise sequential.
    3448              : 
    3449         3585 :         state.dataSolarShading->XVC(1) = XOUT; //? Verify that the IN and OUT values were ever set?
    3450         3585 :         state.dataSolarShading->YVC(1) = YOUT;
    3451         3585 :         state.dataSolarShading->ZVC(1) = 0.0;
    3452         3585 :         state.dataSolarShading->XVC(state.dataSolarShading->NVS) = XIN;
    3453         3585 :         state.dataSolarShading->YVC(state.dataSolarShading->NVS) = YIN;
    3454         3585 :         state.dataSolarShading->ZVC(state.dataSolarShading->NVS) = 0.0;
    3455        10755 :         for (int N = 1; N <= NABOVE; ++N) {
    3456         7170 :             if (NEXT > NVT) {
    3457         3585 :                 NEXT = 1;
    3458              :             }
    3459         7170 :             state.dataSolarShading->XVC(N + 1) = XVT(NEXT);
    3460         7170 :             state.dataSolarShading->YVC(N + 1) = YVT(NEXT);
    3461         7170 :             state.dataSolarShading->ZVC(N + 1) = ZVT(NEXT);
    3462         7170 :             ++NEXT;
    3463              :         }
    3464              :     }
    3465        11826 : }
    3466              : 
    3467        29799 : void CTRANS(EnergyPlusData &state,
    3468              :             int const NS,         // Surface number whose vertex coordinates are being transformed
    3469              :             int const NGRS,       // Base surface number for surface NS
    3470              :             int &NVT,             // Number of vertices for surface NS
    3471              :             Array1D<Real64> &XVT, // XYZ coordinates of vertices of NS in plane of NGRS
    3472              :             Array1D<Real64> &YVT,
    3473              :             Array1D<Real64> &ZVT)
    3474              : {
    3475              : 
    3476              :     // SUBROUTINE INFORMATION:
    3477              :     //       AUTHOR         Legacy Code
    3478              :     //       DATE WRITTEN
    3479              :     //       MODIFIED       na
    3480              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3481              : 
    3482              :     // PURPOSE OF THIS SUBROUTINE:
    3483              :     // Transforms the general coordinates of the vertices
    3484              :     // of surface NS to coordinates in the plane of the receiving surface NGRS.
    3485              :     // See subroutine 'CalcCoordinateTransformation' SurfaceGeometry Module.
    3486              : 
    3487              :     // REFERENCES:
    3488              :     // BLAST/IBLAST code, original author George Walton
    3489              :     // NECAP subroutine 'SHADOW'
    3490              : 
    3491              :     Real64 Xdif; // Intermediate Result
    3492              :     Real64 Ydif; // Intermediate Result
    3493              :     Real64 Zdif; // Intermediate Result
    3494              : 
    3495        29799 :     auto &s_surf = state.dataSurface;
    3496              : 
    3497              :     // Tuned
    3498        29799 :     auto const &surface = s_surf->Surface(NS);
    3499        29799 :     auto const &base_surface = s_surf->Surface(NGRS);
    3500        29799 :     auto const &base_lcsx = base_surface.lcsx;
    3501        29799 :     auto const &base_lcsy = base_surface.lcsy;
    3502        29799 :     auto const &base_lcsz = base_surface.lcsz;
    3503        29799 :     Real64 const base_X0 = s_surf->X0(NGRS);
    3504        29799 :     Real64 const base_Y0 = s_surf->Y0(NGRS);
    3505        29799 :     Real64 const base_Z0 = s_surf->Z0(NGRS);
    3506              : 
    3507        29799 :     NVT = surface.Sides;
    3508              : 
    3509              :     // Perform transformation
    3510       148963 :     for (int N = 1; N <= NVT; ++N) {
    3511       119164 :         auto const &vertex = surface.Vertex(N);
    3512              : 
    3513       119164 :         Xdif = vertex.x - base_X0;
    3514       119164 :         Ydif = vertex.y - base_Y0;
    3515       119164 :         Zdif = vertex.z - base_Z0;
    3516              : 
    3517       119164 :         if (std::abs(Xdif) <= 1.E-15) {
    3518        45200 :             Xdif = 0.0;
    3519              :         }
    3520       119164 :         if (std::abs(Ydif) <= 1.E-15) {
    3521        51546 :             Ydif = 0.0;
    3522              :         }
    3523       119164 :         if (std::abs(Zdif) <= 1.E-15) {
    3524        51492 :             Zdif = 0.0;
    3525              :         }
    3526              : 
    3527       119164 :         XVT(N) = base_lcsx.x * Xdif + base_lcsx.y * Ydif + base_lcsx.z * Zdif;
    3528       119164 :         YVT(N) = base_lcsy.x * Xdif + base_lcsy.y * Ydif + base_lcsy.z * Zdif;
    3529       119164 :         ZVT(N) = base_lcsz.x * Xdif + base_lcsz.y * Ydif + base_lcsz.z * Zdif;
    3530              :     }
    3531        29799 : }
    3532              : 
    3533            0 : void HTRANS(EnergyPlusData &state,
    3534              :             int const I,          // Mode selector: 0 - Compute H.C. of sides
    3535              :             int const NS,         // Figure Number
    3536              :             int const NumVertices // Number of vertices
    3537              : )
    3538              : {
    3539              : 
    3540              :     // SUBROUTINE INFORMATION:
    3541              :     //       AUTHOR         Legacy Code
    3542              :     //       DATE WRITTEN
    3543              :     //       MODIFIED       na
    3544              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3545              : 
    3546              :     // PURPOSE OF THIS SUBROUTINE:
    3547              :     // This subroutine sets up the homogeneous coordinates.
    3548              :     // This routine converts the cartesian coordinates of a surface
    3549              :     // or shadow polygon to homogeneous coordinates.  It also
    3550              :     // computes the area of the polygon.
    3551              : 
    3552              :     // METHODOLOGY EMPLOYED:
    3553              :     // Note: Original legacy code used integer arithmetic (tests in subroutines
    3554              :     // INCLOS and INTCPT are sensitive to round-off error).  However, porting to Fortran 77
    3555              :     // (BLAST/IBLAST) required some variables to become REAL(r64) instead.
    3556              : 
    3557              :     // Notes on homogeneous coordinates:
    3558              :     // A point (X,Y) is represented by a 3-element vector
    3559              :     // (W*X,W*Y,W), where W may be any REAL(r64) number except 0.  a line
    3560              :     // is also represented by a 3-element vector (A,B,C).  The
    3561              :     // directed line (A,B,C) from point (W*X1,W*Y1,W) to point
    3562              :     // (V*X2,V*Y2,V) is given by (A,B,C) = (W*X1,W*Y1,W) cross
    3563              :     // (V*X2,V*Y2,V).  The sequence of the cross product is a
    3564              :     // convention to determine sign.  The condition that a point lie
    3565              :     // on a line is that (A,B,C) dot (W*X,W*Y,W) = 0.  'Normalize'
    3566              :     // the representation of a point by setting W to 1.  Then if
    3567              :     // (A,B,C) dot (X,Y,1) > 0.0, The point is to the left of the
    3568              :     // line, and if it is less than zero, the point is to the right
    3569              :     // of the line.  The intercept of two lines is given by
    3570              :     // (W*X,W*Y,W) = (A1,B1,C1) cross (A2,B2,C3).
    3571              : 
    3572              :     // REFERENCES:
    3573              :     // BLAST/IBLAST code, original author George Walton
    3574              :     // W. M. Newman & R. F. Sproull, 'Principles of Interactive Computer Graphics', Appendix II, McGraw-Hill, 1973.
    3575              :     // 'CRC Math Tables', 22 ED, 'Analytic Geometry', P.369
    3576              : 
    3577              :     // Using/Aliasing
    3578              : 
    3579              :     // Locals
    3580              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3581              :     //                1 - Compute H.C. of vertices & sides
    3582              : 
    3583            0 :     if (NS > 2 * state.dataSolarShading->MaxHCS) {
    3584            0 :         ShowFatalError(state, format("Solar Shading: HTrans: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
    3585              :     }
    3586              : 
    3587            0 :     state.dataSolarShading->HCNV(NS) = NumVertices;
    3588              : 
    3589              :     // Tuned Linear indexing
    3590              : 
    3591            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    3592            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    3593            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    3594            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    3595            0 :     int const l1(state.dataSolarShading->HCX.index(NS, 1));
    3596            0 :     if (I != 0) { // Transform vertices of figure ns.
    3597              : 
    3598              :         // See comment at top of module regarding HCMULT
    3599            0 :         int l(l1);
    3600            0 :         for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
    3601            0 :             state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
    3602            0 :             state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
    3603              :         }
    3604              :     }
    3605              : 
    3606              :     // Establish extra point for finding lines between points.
    3607              : 
    3608            0 :     int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
    3609            0 :     Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
    3610            0 :     Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
    3611              : 
    3612              :     // Determine lines between points.
    3613            0 :     l = l1;
    3614            0 :     int m = l1 + 1u;
    3615              :     Int64 HCX_l;
    3616              :     Int64 HCY_l;
    3617            0 :     Real64 SUM = 0.0;                                  // Sum variable
    3618            0 :     for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
    3619            0 :         HCX_l = HCX_m;
    3620            0 :         HCY_l = HCY_m;
    3621            0 :         HCX_m = state.dataSolarShading->HCX[m];
    3622            0 :         HCY_m = state.dataSolarShading->HCY[m];
    3623            0 :         state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
    3624            0 :         state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
    3625            0 :         SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
    3626              :     }
    3627              : 
    3628              :     // Compute area of polygon.
    3629              :     //  SUM=0.0D0
    3630              :     //  DO N = 1, NumVertices
    3631              :     //    SUM = SUM + HCX(N,NS)*HCY(N+1,NS) - HCY(N,NS)*HCX(N+1,NS) ! Since HCX and HCY integerized, value of SUM should be ok
    3632              :     //  END DO
    3633            0 :     state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
    3634              :     //  HCAREA(NS)=0.5d0*SUM*(kHCMULT)
    3635            0 : }
    3636              : 
    3637        34858 : void HTRANS0(EnergyPlusData &state,
    3638              :              int const NS,         // Figure Number
    3639              :              int const NumVertices // Number of vertices
    3640              : )
    3641              : {
    3642              :     // Using/Aliasing
    3643              : 
    3644              :     // Locals
    3645              : 
    3646        34858 :     if (NS > 2 * state.dataSolarShading->MaxHCS) {
    3647            0 :         ShowFatalError(state, format("Solar Shading: HTrans0: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
    3648              :     }
    3649              : 
    3650        34858 :     state.dataSolarShading->HCNV(NS) = NumVertices;
    3651              : 
    3652              :     // Tuned Linear indexing
    3653              : 
    3654        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    3655        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    3656        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    3657        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    3658              : 
    3659        34858 :     int const l1 = state.dataSolarShading->HCX.index(NS, 1);
    3660              : 
    3661        34858 :     int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
    3662        34858 :     Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l1 ] == ( NS, 1 )
    3663        34858 :     Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l1 ] == ( NS, 1 )
    3664              : 
    3665        34858 :     l = l1;
    3666        34858 :     int m = l1 + 1u;
    3667              :     Int64 HCX_l;
    3668              :     Int64 HCY_l;
    3669        34858 :     Real64 SUM(0.0);
    3670       149503 :     for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
    3671       114645 :         HCX_l = HCX_m;
    3672       114645 :         HCY_l = HCY_m;
    3673       114645 :         HCX_m = state.dataSolarShading->HCX[m];
    3674       114645 :         HCY_m = state.dataSolarShading->HCY[m];
    3675       114645 :         state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
    3676       114645 :         state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
    3677       114645 :         SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
    3678              :     }
    3679              : 
    3680        34858 :     state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
    3681        34858 : }
    3682              : 
    3683        38197 : void HTRANS1(EnergyPlusData &state,
    3684              :              int const NS,         // Figure Number
    3685              :              int const NumVertices // Number of vertices
    3686              : )
    3687              : {
    3688              :     // Using/Aliasing
    3689              : 
    3690        38197 :     if (NS > 2 * state.dataSolarShading->MaxHCS) {
    3691            0 :         ShowFatalError(state, format("Solar Shading: HTrans1: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
    3692              :     }
    3693              : 
    3694        38197 :     state.dataSolarShading->HCNV(NS) = NumVertices;
    3695              : 
    3696              :     // Tuned Linear indexing
    3697              : 
    3698        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    3699        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    3700        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    3701        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    3702              : 
    3703        38197 :     int const l1 = state.dataSolarShading->HCX.index(NS, 1);
    3704              : 
    3705              :     // only in HTRANS1
    3706        38197 :     int l = l1;
    3707       190953 :     for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
    3708       152756 :         state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
    3709       152756 :         state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
    3710              :     }
    3711              : 
    3712        38197 :     l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
    3713        38197 :     Int64 HCX_m(state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]); // [ l1 ] == ( NS, 1 )
    3714        38197 :     Int64 HCY_m(state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]);
    3715              : 
    3716        38197 :     l = l1;
    3717        38197 :     int m = l1 + 1u;
    3718              :     Int64 HCX_l;
    3719              :     Int64 HCY_l;
    3720        38197 :     Real64 SUM = 0.0;
    3721       190953 :     for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
    3722       152756 :         HCX_l = HCX_m;
    3723       152756 :         HCY_l = HCY_m;
    3724       152756 :         HCX_m = state.dataSolarShading->HCX[m];
    3725       152756 :         HCY_m = state.dataSolarShading->HCY[m];
    3726       152756 :         state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
    3727       152756 :         state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
    3728       152756 :         SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
    3729              :     }
    3730              : 
    3731        38197 :     state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
    3732        38197 : }
    3733              : 
    3734            0 : void INCLOS(EnergyPlusData &state,
    3735              :             int const N1,            // Figure number of figure 1
    3736              :             int const N1NumVert,     // Number of vertices of figure 1
    3737              :             int const N2,            // Figure number of figure 2
    3738              :             int const N2NumVert,     // Number of vertices of figure 2
    3739              :             int &NumVerticesOverlap, // Number of vertices which overlap
    3740              :             int &NIN                 // Number of vertices of figure 1 within figure 2
    3741              : )
    3742              : {
    3743              : 
    3744              :     // SUBROUTINE INFORMATION:
    3745              :     //       AUTHOR         Legacy Code
    3746              :     //       DATE WRITTEN
    3747              :     //       MODIFIED       na
    3748              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3749              : 
    3750              :     // PURPOSE OF THIS SUBROUTINE:
    3751              :     // This subroutine determines which vertices of figure N1 lie within figure N2.
    3752              : 
    3753              :     // METHODOLOGY EMPLOYED:
    3754              :     // For vertex N of figure N1 to lie within figure N2, it must be
    3755              :     // on or to the right of all sides of figure N2, assuming
    3756              :     // figure N2 is convex.
    3757              : 
    3758              :     // REFERENCES:
    3759              :     // BLAST/IBLAST code, original author George Walton
    3760              : 
    3761              :     int K;              // Vertex number of the overlap
    3762              :     int M;              // Side number of figure N2
    3763              :     int N;              // Vertex number of figure N1
    3764              :     bool CycleMainLoop; // Sets when to cycle main loop
    3765              :     Real64 HFunct;
    3766              : 
    3767            0 :     NIN = 0;
    3768              : 
    3769            0 :     for (N = 1; N <= N1NumVert; ++N) {
    3770              : 
    3771            0 :         CycleMainLoop = false;
    3772              : 
    3773              :         // Eliminate cases where vertex N is to the left of side M.
    3774              : 
    3775            0 :         for (M = 1; M <= N2NumVert; ++M) {
    3776            0 :             HFunct = state.dataSolarShading->HCX(N1, N) * state.dataSolarShading->HCA(N2, M) +
    3777            0 :                      state.dataSolarShading->HCY(N1, N) * state.dataSolarShading->HCB(N2, M) + state.dataSolarShading->HCC(N2, M);
    3778            0 :             if (HFunct > 0.0) {
    3779            0 :                 CycleMainLoop = true; // Set to cycle to the next value of N
    3780            0 :                 break;                // M DO loop
    3781              :             }
    3782              :         }
    3783              : 
    3784            0 :         if (CycleMainLoop) {
    3785            0 :             continue;
    3786              :         }
    3787            0 :         ++NIN;
    3788              : 
    3789              :         // Check for duplication of previously determined points.
    3790              : 
    3791            0 :         if (NumVerticesOverlap != 0) {
    3792            0 :             for (K = 1; K <= NumVerticesOverlap; ++K) {
    3793            0 :                 if ((state.dataSolarShading->XTEMP(K) == state.dataSolarShading->HCX(N1, N)) &&
    3794            0 :                     (state.dataSolarShading->YTEMP(K) == state.dataSolarShading->HCY(N1, N))) {
    3795            0 :                     CycleMainLoop = true; // Set to cycle to the next value of N
    3796            0 :                     break;                // K DO loop
    3797              :                 }
    3798              :             }
    3799            0 :             if (CycleMainLoop) {
    3800            0 :                 continue;
    3801              :             }
    3802              :         }
    3803              : 
    3804              :         // Record enclosed vertices in temporary arrays.
    3805              : 
    3806            0 :         ++NumVerticesOverlap;
    3807            0 :         state.dataSolarShading->XTEMP(NumVerticesOverlap) = state.dataSolarShading->HCX(N1, N);
    3808            0 :         state.dataSolarShading->YTEMP(NumVerticesOverlap) = state.dataSolarShading->HCY(N1, N);
    3809              :     }
    3810            0 : }
    3811              : 
    3812            0 : void INTCPT(EnergyPlusData &state,
    3813              :             int const NV1, // Number of vertices of figure NS1
    3814              :             int const NV2, // Number of vertices of figure NS2
    3815              :             int &NV3,      // Number of vertices of figure NS3
    3816              :             int const NS1, // Number of the figure being overlapped
    3817              :             int const NS2  // Number of the figure doing overlapping
    3818              : )
    3819              : {
    3820              : 
    3821              :     // SUBROUTINE INFORMATION:
    3822              :     //       AUTHOR         Legacy Code
    3823              :     //       DATE WRITTEN
    3824              :     //       MODIFIED       na
    3825              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3826              : 
    3827              :     // PURPOSE OF THIS SUBROUTINE:
    3828              :     // This subroutine determines all intercepts between the sides of figure NS1
    3829              :     // and the sides of figure NS2.
    3830              : 
    3831              :     // METHODOLOGY EMPLOYED:
    3832              :     // The requirements for intersection are that the end points of
    3833              :     // line N lie on both sides of line M and vice versa.  Also
    3834              :     // eliminate cases where the end point of one line lies exactly
    3835              :     // on the other to reduce duplication with the enclosed points.
    3836              : 
    3837              :     // REFERENCES:
    3838              :     // BLAST/IBLAST code, original author George Walton
    3839              : 
    3840              :     Real64 W;        // Normalization factor
    3841              :     Real64 XUntrunc; // Untruncated X coordinate
    3842              :     Real64 YUntrunc; // Untruncated Y coordinate
    3843              :     Int64 I1;        // Intermediate result for testing intersection
    3844              :     Int64 I2;        // Intermediate result for testing intersection
    3845              :     int K;
    3846              :     int KK;
    3847              :     int M; // Side number of figure NS2
    3848              :     int N; // Side number of figure NS1
    3849              : 
    3850            0 :     for (N = 1; N <= NV1; ++N) {
    3851            0 :         for (M = 1; M <= NV2; ++M) {
    3852              : 
    3853              :             // Eliminate cases where sides N and M do not intersect.
    3854              : 
    3855            0 :             I1 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M) +
    3856            0 :                  state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M) + state.dataSolarShading->HCC(NS1, N);
    3857            0 :             I2 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M + 1) +
    3858            0 :                  state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M + 1) + state.dataSolarShading->HCC(NS1, N);
    3859            0 :             if (I1 >= 0 && I2 >= 0) {
    3860            0 :                 continue;
    3861              :             }
    3862            0 :             if (I1 <= 0 && I2 <= 0) {
    3863            0 :                 continue;
    3864              :             }
    3865              : 
    3866            0 :             I1 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N) +
    3867            0 :                  state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N) + state.dataSolarShading->HCC(NS2, M);
    3868            0 :             I2 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N + 1) +
    3869            0 :                  state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N + 1) + state.dataSolarShading->HCC(NS2, M);
    3870            0 :             if (I1 >= 0 && I2 >= 0) {
    3871            0 :                 continue;
    3872              :             }
    3873            0 :             if (I1 <= 0 && I2 <= 0) {
    3874            0 :                 continue;
    3875              :             }
    3876              : 
    3877              :             // Determine the point of intersection and record in the temporary array.
    3878              : 
    3879            0 :             KK = NV3;
    3880            0 :             ++NV3;
    3881            0 :             W = state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCA(NS1, N) -
    3882            0 :                 state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCB(NS1, N);
    3883            0 :             XUntrunc = (state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCB(NS1, N) -
    3884            0 :                         state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCC(NS1, N)) /
    3885              :                        W;
    3886            0 :             YUntrunc = (state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCC(NS1, N) -
    3887            0 :                         state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCA(NS1, N)) /
    3888              :                        W;
    3889            0 :             if (NV3 > isize(state.dataSolarShading->XTEMP)) {
    3890            0 :                 state.dataSolarShading->XTEMP.redimension(isize(state.dataSolarShading->XTEMP) + 10, 0.0);
    3891            0 :                 state.dataSolarShading->YTEMP.redimension(isize(state.dataSolarShading->YTEMP) + 10, 0.0);
    3892              :             }
    3893            0 :             state.dataSolarShading->XTEMP(NV3) = nint64(XUntrunc);
    3894            0 :             state.dataSolarShading->YTEMP(NV3) = nint64(YUntrunc);
    3895              : 
    3896              :             // Eliminate near-duplicate points.
    3897              : 
    3898            0 :             if (KK != 0) {
    3899            0 :                 Real64 const x(state.dataSolarShading->XTEMP(NV3));
    3900            0 :                 Real64 const y(state.dataSolarShading->YTEMP(NV3));
    3901            0 :                 for (K = 1; K <= KK; ++K) {
    3902            0 :                     if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
    3903            0 :                         continue;
    3904              :                     }
    3905            0 :                     if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
    3906            0 :                         continue;
    3907              :                     }
    3908            0 :                     NV3 = KK;
    3909            0 :                     break; // K DO loop
    3910              :                 }
    3911              :             }
    3912              :         }
    3913              :     }
    3914            0 : }
    3915              : 
    3916         2349 : inline bool neq(Real64 a, Real64 b)
    3917              : {
    3918         2349 :     return std::abs(a - b) > 2.0;
    3919              : }
    3920              : 
    3921         3486 : inline bool d_eq(Real64 a, Real64 b)
    3922              : {
    3923         3486 :     return std::abs(a - b) < 2.0;
    3924              : }
    3925              : 
    3926          737 : void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible)
    3927              : {
    3928              : 
    3929              :     // Line segment clipping
    3930              :     // Reference:
    3931              :     // Liang, Y.D., Barsky, B.A., Slater, M.
    3932              :     // 2D line and polygon clipping based on space subdivision.
    3933              :     // The Visual Computer 10, 407–422 (1994).
    3934              : 
    3935              :     // Tweaked via microbenchmarking to improve efficiency
    3936              : 
    3937          737 :     bool rev = false;
    3938          737 :     if (x0 > x1) { // reverse for efficiency
    3939          311 :         std::swap(x0, x1);
    3940          311 :         std::swap(y0, y1);
    3941          311 :         rev = true;
    3942              :     }
    3943              : 
    3944          737 :     if (x0 > maxX || x1 < minX) {
    3945              :         // Both points are outside the clip window, so they can't cross it
    3946           52 :         return;
    3947              :     }
    3948              : 
    3949              :     // defining variables
    3950          685 :     Real64 const dx = x1 - x0; // >= 0
    3951          685 :     Real64 const dy = y1 - y0;
    3952              : 
    3953          685 :     Real64 const q1 = x0 - minX;
    3954          685 :     Real64 const q2 = maxX - x0;
    3955          685 :     Real64 const q3 = y0 - minY;
    3956          685 :     Real64 const q4 = maxY - y0;
    3957              : 
    3958          685 :     Real64 u1 = 0;
    3959          685 :     Real64 u2 = 1;
    3960              : 
    3961          685 :     if ((dx == 0 && (q1 < 0 || q2 < 0)) || (dy == 0 && (q3 < 0 || q4 < 0))) {
    3962              :         // Line is parallel to clipping window
    3963           98 :         return;
    3964              :     }
    3965          587 :     if (dx != 0) {
    3966          520 :         Real64 const r1 = q1 / -dx;
    3967          520 :         if (r1 > u1) {
    3968          138 :             u1 = r1;
    3969              :         }
    3970          520 :         Real64 const r2 = q2 / dx;
    3971          520 :         if (r2 < u2) {
    3972          136 :             u2 = r2;
    3973              :         }
    3974              :     }
    3975          587 :     if (dy != 0) {
    3976          341 :         Real64 const r3 = q3 / -dy;
    3977          341 :         Real64 const r4 = q4 / dy;
    3978          341 :         if (dy > 0) {
    3979          173 :             if (r3 > u1) {
    3980           54 :                 u1 = r3;
    3981              :             }
    3982          173 :             if (r4 < u2) {
    3983           16 :                 u2 = r4;
    3984              :             }
    3985              :         } else {
    3986          168 :             if (r4 > u1) {
    3987           16 :                 u1 = r4;
    3988              :             }
    3989          168 :             if (r3 < u2) {
    3990           55 :                 u2 = r3;
    3991              :             }
    3992              :         }
    3993              :     }
    3994              : 
    3995          587 :     if (u1 > u2) { // reject
    3996              :         // Line is outside the clipping window
    3997            4 :         return;
    3998              :     }
    3999              : 
    4000          583 :     visible = true;
    4001              : 
    4002          583 :     Real64 const xn0 = x0 + dx * u1;
    4003          583 :     Real64 const yn0 = y0 + dy * u1;
    4004              : 
    4005          583 :     Real64 const xn1 = x0 + dx * u2;
    4006          583 :     Real64 const yn1 = y0 + dy * u2;
    4007              : 
    4008          583 :     if (rev) {
    4009          229 :         x0 = xn1;
    4010          229 :         y0 = yn1;
    4011          229 :         x1 = xn0;
    4012          229 :         y1 = yn0;
    4013              :     } else {
    4014          354 :         x0 = xn0;
    4015          354 :         y0 = yn0;
    4016          354 :         x1 = xn1;
    4017          354 :         y1 = yn1;
    4018              :     }
    4019              : }
    4020              : 
    4021          157 : void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3)
    4022              : {
    4023              :     // Polygon clipping by line segment clipping for rectangles
    4024              :     // Reference:
    4025              :     // Slater, M., Barsky, B.A.
    4026              :     // 2D line and polygon clipping based on space subdivision.
    4027              :     // The Visual Computer 10, 407–422 (1994).
    4028          157 :     bool INTFLAG = false;
    4029          157 :     int l = state.dataSolarShading->HCA.index(NS2, 1);
    4030              :     Real64 maxX, minX, maxY, minY;
    4031          157 :     if (state.dataSolarShading->HCX[l] > state.dataSolarShading->HCX[l + 2]) {
    4032          157 :         maxX = state.dataSolarShading->HCX[l];
    4033          157 :         minX = state.dataSolarShading->HCX[l + 2];
    4034              :     } else {
    4035            0 :         maxX = state.dataSolarShading->HCX[l + 2];
    4036            0 :         minX = state.dataSolarShading->HCX[l];
    4037              :     }
    4038          157 :     if (state.dataSolarShading->HCY[l] > state.dataSolarShading->HCY[l + 2]) {
    4039          157 :         maxY = state.dataSolarShading->HCY[l];
    4040          157 :         minY = state.dataSolarShading->HCY[l + 2];
    4041              :     } else {
    4042            0 :         maxY = state.dataSolarShading->HCY[l + 2];
    4043            0 :         minY = state.dataSolarShading->HCY[l];
    4044              :     }
    4045              : 
    4046              :     Real64 arrx[20]; // Temp array for output X
    4047              :     Real64 arry[20]; // Temp array for output Y
    4048          157 :     int arrc = 0;    // Number of items in output
    4049              : 
    4050          797 :     for (int j = 0; j < NV1; ++j) {
    4051          640 :         Real64 x_1 = state.dataSolarShading->XTEMP[j];
    4052          640 :         Real64 y_1 = state.dataSolarShading->YTEMP[j];
    4053          640 :         Real64 x_2 = state.dataSolarShading->XTEMP[(j + 1) % NV1];
    4054          640 :         Real64 y_2 = state.dataSolarShading->YTEMP[(j + 1) % NV1];
    4055          640 :         Real64 x1 = x_1, x2 = x_2, y1 = y_1, y2 = y_2;
    4056              : 
    4057          640 :         bool visible = false;
    4058          640 :         CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible);
    4059          640 :         if (visible) {
    4060          514 :             if ((x_1 != x1 || y_1 != y1) || (x_2 != x2 || y_2 != y2)) {
    4061          274 :                 INTFLAG = true;
    4062              :             }
    4063              :             // if line on edge, or inside, add both points
    4064          514 :             if (arrc == 0 || ((neq(arrx[arrc - 1], x_1) || neq(arry[arrc - 1], y_1)) && (neq(arrx[0], x_1) || neq(arry[0], y_1)))) {
    4065          213 :                 arrx[arrc] = x_1;
    4066          213 :                 arry[arrc] = y_1;
    4067          213 :                 arrc += 1;
    4068          213 :                 if ((neq(x_1, x_2) || neq(y_1, y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
    4069          183 :                     arrx[arrc] = x_2;
    4070          183 :                     arry[arrc] = y_2;
    4071          183 :                     arrc += 1;
    4072              :                 }
    4073          301 :             } else if ((neq(arrx[arrc - 1], x_2) || neq(arry[arrc - 1], y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
    4074          136 :                 arrx[arrc] = x_2;
    4075          136 :                 arry[arrc] = y_2;
    4076          136 :                 arrc += 1;
    4077              :             }
    4078              :         }
    4079              :     }
    4080          157 :     NV3 = arrc;
    4081              : 
    4082              :     // Re-populate XTEMP/YTEMP
    4083          157 :     if (NV3 > 1) {
    4084          147 :         int LastEdgeIndex = -1, incr = 0;
    4085          147 :         double cornerXs[4] = {minX, minX, maxX, maxX};
    4086          147 :         double cornerYs[4] = {minY, maxY, maxY, minY};
    4087          147 :         Real64 edges[4] = {minX, maxY, maxX, minY};
    4088              :         Real64 LastEdgeX, LastEdgeY;
    4089          826 :         for (int i = 0; i <= arrc; i++) {
    4090          679 :             int k = i % arrc;
    4091              : 
    4092          679 :             Real64 currX = arrx[k], currY = arry[k];
    4093              : 
    4094          679 :             int edgeCount = 0, EdgeIndex = -1;
    4095         3395 :             for (int m = 0; m < 4; m++) {
    4096         2716 :                 if (m % 2 == 0 && d_eq(currX, edges[m])) { // MinX or MaxX
    4097          486 :                     edgeCount++;
    4098          486 :                     EdgeIndex = m;
    4099         2230 :                 } else if (m % 2 == 1 && d_eq(currY, edges[m])) {
    4100          501 :                     edgeCount++;
    4101          501 :                     EdgeIndex = m;
    4102              :                 }
    4103              :             }
    4104          679 :             if (edgeCount == 0) { // On inside
    4105           77 :                 if (i != arrc) {
    4106           77 :                     state.dataSolarShading->XTEMP[incr] = currX;
    4107           77 :                     state.dataSolarShading->YTEMP[incr] = currY;
    4108           77 :                     incr++;
    4109              :                 }
    4110           77 :                 continue;
    4111          602 :             } else if (edgeCount > 1) { // On corner
    4112          385 :                 if (d_eq(currX, minX)) {
    4113          250 :                     if (d_eq(currY, minY)) {
    4114            8 :                         EdgeIndex = 3;
    4115              :                     } else {
    4116          242 :                         EdgeIndex = 0;
    4117              :                     }
    4118              :                 } else {
    4119          135 :                     if (d_eq(currY, maxY)) {
    4120          131 :                         EdgeIndex = 1;
    4121              :                     } else {
    4122            4 :                         EdgeIndex = 2;
    4123              :                     }
    4124              :                 }
    4125              :             }
    4126          602 :             if ((LastEdgeIndex > -1 && EdgeIndex > -1) && LastEdgeIndex != EdgeIndex) {
    4127          386 :                 int jumpCount = 0;
    4128          386 :                 if ((EdgeIndex == 0 && LastEdgeIndex == 3) || (EdgeIndex - LastEdgeIndex == 1)) {
    4129          237 :                     jumpCount = 1;
    4130          149 :                 } else if (EdgeIndex % 2 == LastEdgeIndex % 2) {
    4131              :                     // Clockwise double jump
    4132          112 :                     jumpCount = 2;
    4133           37 :                 } else if ((EdgeIndex == 3 && LastEdgeIndex == 0) || (LastEdgeIndex - EdgeIndex == 1)) {
    4134              :                     // Clockwise triple jump
    4135           37 :                     jumpCount = 3;
    4136              :                 }
    4137          386 :                 if (jumpCount > 0) {
    4138              :                     Real64 cornerX;
    4139              :                     Real64 cornerY;
    4140          386 :                     int startIndex = (LastEdgeIndex + 1) % 4;
    4141          386 :                     int added = 0;
    4142          958 :                     for (int i1 = startIndex, j1 = 0; j1 < jumpCount; i1 = (i1 + 1) % 4, j1++) {
    4143          572 :                         cornerX = cornerXs[i1];
    4144          572 :                         cornerY = cornerYs[i1];
    4145          572 :                         if (cornerX == LastEdgeX && cornerY == LastEdgeY) {
    4146          264 :                             continue; // skip if jump started on corner
    4147              :                         }
    4148              : 
    4149          308 :                         bool insideFlag = true;
    4150          979 :                         for (int j = 0; j < NV1; ++j) {
    4151          921 :                             if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) +
    4152          921 :                                     state.dataSolarShading->CTEMP[j] >
    4153              :                                 0.0) {
    4154          250 :                                 insideFlag = false;
    4155          250 :                                 break;
    4156              :                             }
    4157              :                         }
    4158              : 
    4159          366 :                         if (insideFlag &&
    4160           58 :                             (incr == 0 ||
    4161          144 :                              ((neq(cornerX, state.dataSolarShading->XTEMP[incr - 1]) || neq(cornerY, state.dataSolarShading->YTEMP[incr - 1])) &&
    4162           84 :                               (neq(cornerX, state.dataSolarShading->XTEMP[0]) || neq(cornerY, state.dataSolarShading->YTEMP[0]))))) {
    4163           56 :                             state.dataSolarShading->XTEMP[incr] = cornerX;
    4164           56 :                             state.dataSolarShading->YTEMP[incr] = cornerY;
    4165           56 :                             incr++;
    4166           56 :                             added++;
    4167              :                         }
    4168              :                     }
    4169          386 :                     if (jumpCount > 2 && (added == jumpCount && edgeCount == 1)) {
    4170            0 :                         if (i != arrc) {
    4171            0 :                             state.dataSolarShading->XTEMP[incr] = currX;
    4172            0 :                             state.dataSolarShading->YTEMP[incr] = currY;
    4173            0 :                             incr++;
    4174              :                         }
    4175            0 :                         break;
    4176              :                     }
    4177              :                 }
    4178              :             }
    4179          602 :             if (i != arrc) {
    4180          455 :                 state.dataSolarShading->XTEMP[incr] = currX;
    4181          455 :                 state.dataSolarShading->YTEMP[incr] = currY;
    4182          455 :                 incr++;
    4183              :             }
    4184          602 :             LastEdgeIndex = EdgeIndex;
    4185          602 :             LastEdgeX = currX;
    4186          602 :             LastEdgeY = currY;
    4187              :         }
    4188          147 :         NV3 = incr;
    4189              : 
    4190              :     } else {
    4191           10 :         if (NV3 == 1) {
    4192            0 :             state.dataSolarShading->XTEMP[0] = arrx[0];
    4193            0 :             state.dataSolarShading->YTEMP[0] = arry[0];
    4194              :         }
    4195           10 :         if (NV3 == 0) {
    4196           10 :             double cornerXs[4] = {minX, minX, maxX, maxX};
    4197           10 :             double cornerYs[4] = {minY, maxY, maxY, minY};
    4198           10 :             Real64 cornerX = cornerXs[0];
    4199           10 :             Real64 cornerY = cornerYs[0];
    4200           10 :             bool insideFlag = true;
    4201           50 :             for (int j = 0; j < NV1; ++j) {
    4202           40 :                 if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) + state.dataSolarShading->CTEMP[j] >=
    4203              :                     0.0) {
    4204            0 :                     insideFlag = false;
    4205            0 :                     break;
    4206              :                 }
    4207              :             }
    4208           10 :             if (insideFlag) {
    4209           50 :                 for (int i1 = 0; i1 < 4; i1++) {
    4210           40 :                     state.dataSolarShading->XTEMP[i1] = cornerXs[i1];
    4211           40 :                     state.dataSolarShading->YTEMP[i1] = cornerYs[i1];
    4212              :                 }
    4213           10 :                 NV3 = 4;
    4214           10 :                 INTFLAG = true;
    4215              :             }
    4216              :         }
    4217              :     }
    4218              : 
    4219              :     // update homogeneous edges A,B,C
    4220          157 :     if (NV3 > 0) {
    4221          157 :         Real64 const X_0(state.dataSolarShading->XTEMP[0]);
    4222          157 :         Real64 const Y_0(state.dataSolarShading->YTEMP[0]);
    4223          157 :         Real64 XP_0 = X_0, XP_1;
    4224          157 :         Real64 YP_0 = Y_0, YP_1;
    4225          628 :         for (int P = 0; P < NV3 - 1; ++P) {
    4226          471 :             XP_1 = state.dataSolarShading->XTEMP[P + 1];
    4227          471 :             YP_1 = state.dataSolarShading->YTEMP[P + 1];
    4228              : 
    4229          471 :             state.dataSolarShading->ATEMP[P] = YP_0 - YP_1;
    4230          471 :             state.dataSolarShading->BTEMP[P] = XP_1 - XP_0;
    4231          471 :             state.dataSolarShading->CTEMP[P] = XP_0 * YP_1 - YP_0 * XP_1;
    4232          471 :             XP_0 = XP_1;
    4233          471 :             YP_0 = YP_1;
    4234              :         }
    4235              : 
    4236          157 :         state.dataSolarShading->ATEMP[NV3 - 1] = YP_1 - Y_0;
    4237          157 :         state.dataSolarShading->BTEMP[NV3 - 1] = X_0 - XP_1;
    4238          157 :         state.dataSolarShading->CTEMP[NV3 - 1] = XP_1 * Y_0 - YP_1 * X_0;
    4239              :     }
    4240              : 
    4241              :     // Determine overlap status
    4242          157 :     if (NV3 < 3) { // Determine overlap status
    4243            0 :         state.dataSolarShading->OverlapStatus = NoOverlap;
    4244          157 :     } else if (!INTFLAG) {
    4245           12 :         state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
    4246              :     }
    4247          157 : }
    4248              : 
    4249        20917 : void CLIPPOLY(EnergyPlusData &state,
    4250              :               int const NS1, // Figure number of figure 1 (The subject polygon)
    4251              :               int const NS2, // Figure number of figure 2 (The clipping polygon)
    4252              :               int const NV1, // Number of vertices of figure 1
    4253              :               int const NV2, // Number of vertices of figure 2
    4254              :               int &NV3       // Number of vertices of figure 3
    4255              : )
    4256              : {
    4257              : 
    4258              :     // SUBROUTINE INFORMATION:
    4259              :     //       AUTHOR         Tyler Hoyt
    4260              :     //       DATE WRITTEN   May 4, 2010
    4261              :     //       MODIFIED       na
    4262              :     //       RE-ENGINEERED  na
    4263              : 
    4264              :     // PURPOSE OF THIS SUBROUTINE:
    4265              :     // Populate global arrays XTEMP and YTEMP with the vertices
    4266              :     // of the overlap between NS1 and NS2, and determine relevant
    4267              :     // overlap status.
    4268              : 
    4269              :     // METHODOLOGY EMPLOYED:
    4270              :     // The Sutherland-Hodgman algorithm for polygon clipping is employed.
    4271              : 
    4272              :     using General::SafeDivide;
    4273              : 
    4274              :     typedef Array2D<Int64>::size_type size_type;
    4275              :     bool INTFLAG; // For overlap status
    4276              :     int S;        // Test vertex
    4277              :     int KK;       // Duplicate test index
    4278              :     int NVOUT;    // Current output length for loops
    4279              :     int NVTEMP;
    4280              : 
    4281              :     Real64 W; // Normalization factor
    4282              :     Real64 HFunct;
    4283              : 
    4284        20917 :     auto &s_surf = state.dataSurface;
    4285              : 
    4286              : #ifdef EP_Count_Calls
    4287              :     ++state.dataTimingsData->NumClipPoly_Calls;
    4288              : #endif
    4289              :     // Tuned Linear indexing
    4290              : 
    4291        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    4292        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    4293        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    4294        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    4295              : 
    4296              :     // Populate the arrays with the original polygon
    4297       104901 :     for (size_type j = 0, l = state.dataSolarShading->HCX.index(NS1, 1), e = NV1; j < e; ++j, ++l) {
    4298        83984 :         state.dataSolarShading->XTEMP[j] = state.dataSolarShading->HCX[l]; // [ l ] == ( NS1, j+1 )
    4299        83984 :         state.dataSolarShading->YTEMP[j] = state.dataSolarShading->HCY[l];
    4300        83984 :         state.dataSolarShading->ATEMP[j] = state.dataSolarShading->HCA[l];
    4301        83984 :         state.dataSolarShading->BTEMP[j] = state.dataSolarShading->HCB[l];
    4302        83984 :         state.dataSolarShading->CTEMP[j] = state.dataSolarShading->HCC[l];
    4303              :     }
    4304              : 
    4305        20917 :     NVOUT = NV1; // First point-loop is the length of the subject polygon.
    4306        20917 :     INTFLAG = false;
    4307        20917 :     NVTEMP = 0;
    4308        20917 :     KK = 0;
    4309              : 
    4310              :     // Check if clipping polygon is rectangle
    4311        20917 :     if (state.dataSysVars->SlaterBarsky) {
    4312          422 :         int l1 = state.dataSolarShading->HCA.index(NS2, 1);
    4313          844 :         bool rectFlag = ((NV2 == 4) && (((((state.dataSolarShading->HCX[l1] == state.dataSolarShading->HCX[l1 + 1] &&
    4314          157 :                                             state.dataSolarShading->HCY[l1] != state.dataSolarShading->HCY[l1 + 1]) &&
    4315          157 :                                            ((state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 1] &&
    4316          157 :                                              state.dataSolarShading->HCY[l1 + 3] == state.dataSolarShading->HCY[l1]))) &&
    4317          157 :                                           state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 3]) ||
    4318          265 :                                          ((((state.dataSolarShading->HCY[l1] == state.dataSolarShading->HCY[l1 + 1] &&
    4319           24 :                                              state.dataSolarShading->HCX[l1] != state.dataSolarShading->HCX[l1 + 1]) &&
    4320           24 :                                             (state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 1] &&
    4321            0 :                                              state.dataSolarShading->HCX[l1 + 3] == state.dataSolarShading->HCX[l1])) &&
    4322            0 :                                            (state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 3]))))));
    4323          422 :         if (rectFlag) {
    4324          157 :             CLIPRECT(state, NS2, NV1, NV3);
    4325          157 :             return;
    4326              :         }
    4327              :     }
    4328              : 
    4329        20760 :     int l = state.dataSolarShading->HCA.index(NS2, 1);
    4330        88491 :     for (int E = 1; E <= NV2; ++E, ++l) { // Loop over edges of the clipping polygon
    4331       377790 :         for (int P = 1; P <= NVOUT; ++P) {
    4332       304257 :             state.dataSolarShading->XTEMP1(P) = state.dataSolarShading->XTEMP(P);
    4333       304257 :             state.dataSolarShading->YTEMP1(P) = state.dataSolarShading->YTEMP(P);
    4334              :         }
    4335        73533 :         S = NVOUT;
    4336        73533 :         Real64 const HCA_E(state.dataSolarShading->HCA[l]);
    4337        73533 :         Real64 const HCB_E(state.dataSolarShading->HCB[l]);
    4338        73533 :         Real64 const HCC_E(state.dataSolarShading->HCC[l]);
    4339        73533 :         Real64 XTEMP1_S(state.dataSolarShading->XTEMP1(S));
    4340        73533 :         Real64 YTEMP1_S(state.dataSolarShading->YTEMP1(S));
    4341       377790 :         for (int P = 1; P <= NVOUT; ++P) {
    4342       304257 :             Real64 const XTEMP1_P(state.dataSolarShading->XTEMP1(P));
    4343       304257 :             Real64 const YTEMP1_P(state.dataSolarShading->YTEMP1(P));
    4344       304257 :             HFunct = XTEMP1_P * HCA_E + YTEMP1_P * HCB_E + HCC_E;
    4345              :             // S is constant within this block
    4346       304257 :             if (HFunct <= 0.0) { // Vertex is not in the clipping plane
    4347       222766 :                 HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
    4348       222766 :                 if (HFunct > 0.0) { // Test vertex is in the clipping plane
    4349              : 
    4350              :                     // Find/store the intersection of the clip edge and the line connecting S and P
    4351        30580 :                     KK = NVTEMP;
    4352        30580 :                     ++NVTEMP;
    4353        30580 :                     Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
    4354        30580 :                     Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
    4355        30580 :                     Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
    4356        30580 :                     W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
    4357        30580 :                     if (W != 0.0) {
    4358        30580 :                         Real64 const W_inv(1.0 / W);
    4359        30580 :                         state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
    4360        30580 :                         state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
    4361              :                     } else {
    4362            0 :                         state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
    4363            0 :                         state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
    4364              :                     }
    4365        30580 :                     INTFLAG = true;
    4366              : 
    4367        30580 :                     if (E == NV2) { // Remove near-duplicates on last edge
    4368         6024 :                         if (KK != 0) {
    4369         3585 :                             Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
    4370         3585 :                             Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
    4371         8189 :                             for (int K = 1; K <= KK; ++K) {
    4372         4604 :                                 if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
    4373         4463 :                                     continue;
    4374              :                                 }
    4375          141 :                                 if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
    4376          141 :                                     continue;
    4377              :                                 }
    4378            0 :                                 NVTEMP = KK;
    4379            0 :                                 break; // K loop
    4380              :                             }
    4381              :                         }
    4382              :                     }
    4383              :                 }
    4384              : 
    4385       222766 :                 KK = NVTEMP;
    4386       222766 :                 ++NVTEMP;
    4387       222766 :                 if (NVTEMP > state.dataSolarShading->MAXHCArrayBounds) {
    4388            0 :                     int const NewArrayBounds(state.dataSolarShading->MAXHCArrayBounds + state.dataSolarShading->MAXHCArrayIncrement);
    4389            0 :                     state.dataSolarShading->XTEMP.redimension(NewArrayBounds, 0.0);
    4390            0 :                     state.dataSolarShading->YTEMP.redimension(NewArrayBounds, 0.0);
    4391            0 :                     state.dataSolarShading->XTEMP1.redimension(NewArrayBounds, 0.0);
    4392            0 :                     state.dataSolarShading->YTEMP1.redimension(NewArrayBounds, 0.0);
    4393            0 :                     state.dataSolarShading->ATEMP.redimension(NewArrayBounds, 0.0);
    4394            0 :                     state.dataSolarShading->BTEMP.redimension(NewArrayBounds, 0.0);
    4395            0 :                     state.dataSolarShading->CTEMP.redimension(NewArrayBounds, 0.0);
    4396            0 :                     state.dataSolarShading->MAXHCArrayBounds = NewArrayBounds;
    4397              :                 }
    4398              : 
    4399       222766 :                 state.dataSolarShading->XTEMP(NVTEMP) = XTEMP1_P;
    4400       222766 :                 state.dataSolarShading->YTEMP(NVTEMP) = YTEMP1_P;
    4401              : 
    4402       222766 :                 if (E == NV2) { // Remove near-duplicates on last edge
    4403        50965 :                     if (KK != 0) {
    4404        41120 :                         Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
    4405        41120 :                         Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
    4406       120257 :                         for (int K = 1; K <= KK; ++K) {
    4407        83665 :                             if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
    4408        62637 :                                 continue;
    4409              :                             }
    4410        21028 :                             if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
    4411        16500 :                                 continue;
    4412              :                             }
    4413         4528 :                             NVTEMP = KK;
    4414         4528 :                             break; // K loop
    4415              :                         }
    4416              :                     }
    4417              :                 }
    4418              : 
    4419              :             } else {
    4420        81491 :                 HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
    4421        81491 :                 if (HFunct <= 0.0) {                                        // Test vertex is not in the clipping plane
    4422        30580 :                     if (NVTEMP < 2 * (s_surf->MaxVerticesPerSurface + 1)) { // avoid assigning to element outside of XTEMP array size
    4423        30580 :                         KK = NVTEMP;
    4424        30580 :                         ++NVTEMP;
    4425        30580 :                         Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
    4426        30580 :                         Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
    4427        30580 :                         Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
    4428        30580 :                         W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
    4429        30580 :                         if (W != 0.0) {
    4430        30580 :                             Real64 const W_inv(1.0 / W);
    4431        30580 :                             state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
    4432        30580 :                             state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
    4433              :                         } else {
    4434            0 :                             state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
    4435            0 :                             state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
    4436              :                         }
    4437        30580 :                         INTFLAG = true;
    4438              : 
    4439        30580 :                         if (E == NV2) { // Remove near-duplicates on last edge
    4440         6024 :                             if (KK != 0) {
    4441         3350 :                                 Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
    4442         3350 :                                 Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
    4443        11212 :                                 for (int K = 1; K <= KK; ++K) {
    4444         8062 :                                     if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
    4445         6525 :                                         continue;
    4446              :                                     }
    4447         1537 :                                     if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
    4448         1337 :                                         continue;
    4449              :                                     }
    4450          200 :                                     NVTEMP = KK;
    4451          200 :                                     break; // K loop
    4452              :                                 }
    4453              :                             }
    4454              :                         }
    4455              :                     }
    4456              :                 }
    4457              :             }
    4458       304257 :             S = P;
    4459       304257 :             XTEMP1_S = XTEMP1_P;
    4460       304257 :             YTEMP1_S = YTEMP1_P;
    4461              :         } // end loop over points of subject polygon
    4462              : 
    4463        73533 :         NVOUT = NVTEMP;
    4464        73533 :         if (NVOUT == 0) {
    4465         5802 :             break; // Added to avoid array bounds violation of XTEMP1 and YTEMP1 and wasted looping
    4466              :         }
    4467        67731 :         NVTEMP = 0;
    4468              : 
    4469        67731 :         if (E != NV2) {
    4470        52773 :             if (NVOUT > 2) { // Compute HC values for edges of output polygon
    4471        52773 :                 Real64 const X_1(state.dataSolarShading->XTEMP(1));
    4472        52773 :                 Real64 const Y_1(state.dataSolarShading->YTEMP(1));
    4473        52773 :                 Real64 X_P(X_1), X_P1;
    4474        52773 :                 Real64 Y_P(Y_1), Y_P1;
    4475       220913 :                 for (int P = 1; P < NVOUT; ++P) {
    4476       168140 :                     X_P1 = state.dataSolarShading->XTEMP(P + 1);
    4477       168140 :                     Y_P1 = state.dataSolarShading->YTEMP(P + 1);
    4478       168140 :                     state.dataSolarShading->ATEMP(P) = Y_P - Y_P1;
    4479       168140 :                     state.dataSolarShading->BTEMP(P) = X_P1 - X_P;
    4480       168140 :                     state.dataSolarShading->CTEMP(P) = X_P * Y_P1 - Y_P * X_P1;
    4481       168140 :                     X_P = X_P1;
    4482       168140 :                     Y_P = Y_P1;
    4483              :                 }
    4484        52773 :                 state.dataSolarShading->ATEMP(NVOUT) = Y_P1 - Y_1;
    4485        52773 :                 state.dataSolarShading->BTEMP(NVOUT) = X_1 - X_P1;
    4486        52773 :                 state.dataSolarShading->CTEMP(NVOUT) = X_P1 * Y_1 - Y_P1 * X_1;
    4487              :             }
    4488              :         }
    4489              : 
    4490              :     } // end loop over edges in NS2
    4491              : 
    4492        20760 :     NV3 = NVOUT;
    4493              : 
    4494        20760 :     if (NV3 < 3) { // Determine overlap status
    4495         6406 :         state.dataSolarShading->OverlapStatus = NoOverlap;
    4496        14354 :     } else if (!INTFLAG) {
    4497         1557 :         state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
    4498              :     }
    4499              : }
    4500              : 
    4501         5346 : void MULTOL(EnergyPlusData &state,
    4502              :             int const NNN,   // argument
    4503              :             int const LOC0,  // Location in the homogeneous coordinate array
    4504              :             int const NRFIGS // Number of figures overlapped
    4505              : )
    4506              : {
    4507              : 
    4508              :     // SUBROUTINE INFORMATION:
    4509              :     //       AUTHOR         Legacy Code
    4510              :     //       DATE WRITTEN
    4511              :     //       MODIFIED       na
    4512              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4513              : 
    4514              :     // PURPOSE OF THIS SUBROUTINE:
    4515              :     // This subroutine determines the overlaps of figure 'NS2' with previous figures
    4516              :     // 'LOC0+1' through 'LOC0+NRFIGS'.  For example, if NS2
    4517              :     // is a shadow, overlap with previous shadows.
    4518              : 
    4519              :     // REFERENCES:
    4520              :     // BLAST/IBLAST code, original author George Walton
    4521              : 
    4522              :     int I;   // Loop Control
    4523              :     int NS1; // Number of the figure being overlapped
    4524              :     int NS2; // Number of the figure doing overlapping
    4525              :     int NS3; // Location to place results of overlap
    4526              : 
    4527         5346 :     state.dataSolarShading->maxNumberOfFigures = max(state.dataSolarShading->maxNumberOfFigures, NRFIGS);
    4528              : 
    4529         5346 :     NS2 = NNN;
    4530        12252 :     for (I = 1; I <= NRFIGS; ++I) {
    4531         6906 :         NS1 = LOC0 + I;
    4532         6906 :         NS3 = state.dataSolarShading->LOCHCA + 1;
    4533              : 
    4534         6906 :         DeterminePolygonOverlap(state, NS1, NS2, NS3); // Find overlap of figure NS2 on figure NS1.
    4535              : 
    4536              :         // Process overlap cases:
    4537              : 
    4538         6906 :         if (state.dataSolarShading->OverlapStatus == NoOverlap) {
    4539         1604 :             continue;
    4540              :         }
    4541              : 
    4542         5302 :         if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    4543            0 :             break;
    4544              :         }
    4545              : 
    4546         5302 :         state.dataSolarShading->LOCHCA = NS3; // Increment h.c. arrays pointer.
    4547              :     }
    4548         5346 : }
    4549              : 
    4550            0 : void ORDER(EnergyPlusData &state,
    4551              :            int const NV3, // Number of vertices of figure NS3
    4552              :            int const NS3  // Location to place results of overlap
    4553              : )
    4554              : {
    4555              : 
    4556              :     // SUBROUTINE INFORMATION:
    4557              :     //       AUTHOR         Legacy Code
    4558              :     //       DATE WRITTEN
    4559              :     //       MODIFIED       na
    4560              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4561              : 
    4562              :     // PURPOSE OF THIS SUBROUTINE:
    4563              :     // This subroutine sorts the vertices found by inclosure and
    4564              :     // intercept in to clockwise order so that the overlap polygon
    4565              :     // may be used in computing subsequent overlaps.
    4566              : 
    4567              :     // METHODOLOGY EMPLOYED:
    4568              :     // The slopes of the lines from the left-most vertex to all
    4569              :     // others are found.  The slopes are sorted into descending
    4570              :     // sequence.  This sequence puts the vertices in clockwise order.
    4571              : 
    4572              :     // REFERENCES:
    4573              :     // BLAST/IBLAST code, original author George Walton
    4574              : 
    4575              :     Real64 DELTAX; // Difference between X coordinates of two vertices
    4576              :     Real64 DELTAY; // Difference between Y coordinates of two vertices
    4577              :     Real64 SAVES;  // Temporary location for exchange of variables
    4578              :     Real64 SAVEX;  // Temporary location for exchange of variables
    4579              :     Real64 SAVEY;  // Temporary location for exchange of variables
    4580              :     Real64 XMIN;   // X coordinate of left-most vertex
    4581              :     Real64 YXMIN;
    4582              :     int I;   // Sort index
    4583              :     int IM1; // Sort control
    4584              :     int J;   // Sort index
    4585              :     int M;   // Number of slopes to be sorted
    4586              :     int N;   // Vertex number
    4587              :     int P;   // Location of first slope to be sorted
    4588              : 
    4589            0 :     auto &s_surf = state.dataSurface;
    4590              : 
    4591            0 :     if (state.dataSolarShading->ORDERFirstTimeFlag) {
    4592            0 :         state.dataSolarShading->SLOPE.allocate(max(10, s_surf->MaxVerticesPerSurface + 1));
    4593            0 :         state.dataSolarShading->ORDERFirstTimeFlag = false;
    4594              :     }
    4595              :     // Determine left-most vertex.
    4596              : 
    4597            0 :     XMIN = state.dataSolarShading->XTEMP(1);
    4598            0 :     YXMIN = state.dataSolarShading->YTEMP(1);
    4599            0 :     for (N = 2; N <= NV3; ++N) {
    4600            0 :         if (state.dataSolarShading->XTEMP(N) >= XMIN) {
    4601            0 :             continue;
    4602              :         }
    4603            0 :         XMIN = state.dataSolarShading->XTEMP(N);
    4604            0 :         YXMIN = state.dataSolarShading->YTEMP(N);
    4605              :     }
    4606              : 
    4607              :     // Determine slopes from left-most vertex to all others.  Identify
    4608              :     // first and second or last points as they occur.
    4609              : 
    4610            0 :     P = 1;
    4611            0 :     M = 0;
    4612            0 :     for (N = 1; N <= NV3; ++N) {
    4613              : 
    4614            0 :         DELTAX = state.dataSolarShading->XTEMP(N) - XMIN;
    4615            0 :         DELTAY = state.dataSolarShading->YTEMP(N) - YXMIN;
    4616              : 
    4617            0 :         if (std::abs(DELTAX) > 0.5) {
    4618              : 
    4619            0 :             ++M;
    4620            0 :             state.dataSolarShading->SLOPE(M) = DELTAY / DELTAX;
    4621            0 :             state.dataSolarShading->XTEMP(M) = state.dataSolarShading->XTEMP(N);
    4622            0 :             state.dataSolarShading->YTEMP(M) = state.dataSolarShading->YTEMP(N);
    4623              : 
    4624            0 :         } else if (DELTAY > 0.5) {
    4625              : 
    4626            0 :             P = 2;
    4627            0 :             state.dataSolarShading->HCX(NS3, 2) = nint64(state.dataSolarShading->XTEMP(N));
    4628            0 :             state.dataSolarShading->HCY(NS3, 2) = nint64(state.dataSolarShading->YTEMP(N));
    4629              : 
    4630            0 :         } else if (DELTAY < -0.5) {
    4631              : 
    4632            0 :             state.dataSolarShading->HCX(NS3, NV3) = nint64(state.dataSolarShading->XTEMP(N));
    4633            0 :             state.dataSolarShading->HCY(NS3, NV3) = nint64(state.dataSolarShading->YTEMP(N));
    4634              : 
    4635              :         } else {
    4636              : 
    4637            0 :             state.dataSolarShading->HCX(NS3, 1) = nint64(XMIN);
    4638            0 :             state.dataSolarShading->HCY(NS3, 1) = nint64(YXMIN);
    4639              :         }
    4640              :     }
    4641              : 
    4642              :     // Sequence the temporary arrays in order of decreasing slopes.(bubble sort)
    4643              : 
    4644            0 :     if (M != 1) {
    4645              : 
    4646            0 :         for (I = 2; I <= M; ++I) {
    4647            0 :             IM1 = I - 1;
    4648            0 :             for (J = 1; J <= IM1; ++J) {
    4649            0 :                 if (state.dataSolarShading->SLOPE(I) <= state.dataSolarShading->SLOPE(J)) {
    4650            0 :                     continue;
    4651              :                 }
    4652            0 :                 SAVEX = state.dataSolarShading->XTEMP(I);
    4653            0 :                 SAVEY = state.dataSolarShading->YTEMP(I);
    4654            0 :                 SAVES = state.dataSolarShading->SLOPE(I);
    4655            0 :                 state.dataSolarShading->XTEMP(I) = state.dataSolarShading->XTEMP(J);
    4656            0 :                 state.dataSolarShading->YTEMP(I) = state.dataSolarShading->YTEMP(J);
    4657            0 :                 state.dataSolarShading->SLOPE(I) = state.dataSolarShading->SLOPE(J);
    4658            0 :                 state.dataSolarShading->XTEMP(J) = SAVEX;
    4659            0 :                 state.dataSolarShading->YTEMP(J) = SAVEY;
    4660            0 :                 state.dataSolarShading->SLOPE(J) = SAVES;
    4661              :             }
    4662              :         }
    4663              :     }
    4664              : 
    4665              :     // Place sequenced points in the homogeneous coordinate arrays.
    4666              : 
    4667            0 :     for (N = 1; N <= M; ++N) {
    4668            0 :         state.dataSolarShading->HCX(NS3, N + P) = nint64(state.dataSolarShading->XTEMP(N));
    4669            0 :         state.dataSolarShading->HCY(NS3, N + P) = nint64(state.dataSolarShading->YTEMP(N));
    4670              :     }
    4671            0 : }
    4672              : 
    4673        20917 : void DeterminePolygonOverlap(EnergyPlusData &state,
    4674              :                              int const NS1, // Number of the figure being overlapped
    4675              :                              int const NS2, // Number of the figure doing overlapping
    4676              :                              int const NS3  // Location to place results of overlap
    4677              : )
    4678              : {
    4679              : 
    4680              :     // SUBROUTINE INFORMATION:
    4681              :     //       AUTHOR         Legacy Code
    4682              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4683              : 
    4684              :     // PURPOSE OF THIS SUBROUTINE:
    4685              :     // This subroutine computes the possible overlap of two polygons.
    4686              :     // It uses homogeneous coordinate techniques to determine the overlap area
    4687              :     // between two convex polygons.  Results are stored in the homogeneous coordinate (HC) arrays.
    4688              : 
    4689              :     // METHODOLOGY EMPLOYED:
    4690              :     // The vertices defining the overlap between fig.1 and fig.2
    4691              :     // consist of: the vertices of fig.1 enclosed by fig.2 (A)
    4692              :     // plus the vertices of fig.2 enclosed by fig.1 (B)
    4693              :     // plus the intercepts of fig.1 and fig.2 (C & D)
    4694              : 
    4695              :     //                               +----------------------+
    4696              :     //                               !                      !
    4697              :     //                               !         FIG.2        !
    4698              :     //                               !                      !
    4699              :     //                +--------------C----------A           !
    4700              :     //                !              !         /            !
    4701              :     //                !              !        /             !
    4702              :     //                !              B-------D--------------+
    4703              :     //                !    FIG.1            /
    4704              :     //                !                    /
    4705              :     //                +-------------------+
    4706              : 
    4707              :     // REFERENCES:
    4708              :     // BLAST/IBLAST code, original author George Walton
    4709              : 
    4710              : #ifdef EP_Count_Calls
    4711              :     ++state.dataTimingsData->NumDetPolyOverlap_Calls;
    4712              : #endif
    4713              : 
    4714              :     // Check for exceeding array limits.
    4715        20917 :     if (NS3 > state.dataSolarShading->MaxHCS) {
    4716              : 
    4717            0 :         state.dataSolarShading->OverlapStatus = TooManyFigures;
    4718              : 
    4719            0 :         if (!state.dataSolarShading->TooManyFiguresMessage && !state.dataGlobal->DisplayExtraWarnings) {
    4720            0 :             ShowWarningError(state,
    4721            0 :                              format("DeterminePolygonOverlap: Too many figures [>{}]  detected in an overlap calculation. Use "
    4722              :                                     "Output:Diagnostics,DisplayExtraWarnings; for more details.",
    4723            0 :                                     state.dataSolarShading->MaxHCS));
    4724            0 :             state.dataSolarShading->TooManyFiguresMessage = true;
    4725              :         }
    4726              : 
    4727            0 :         if (state.dataGlobal->DisplayExtraWarnings) {
    4728            0 :             state.dataSolarShading->TrackTooManyFigures.redimension(++state.dataSolarShading->NumTooManyFigures);
    4729            0 :             state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex1 =
    4730            0 :                 state.dataSolarShading->CurrentShadowingSurface;
    4731            0 :             state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex2 =
    4732            0 :                 state.dataSolarShading->CurrentSurfaceBeingShadowed;
    4733              :         }
    4734              : 
    4735            0 :         return;
    4736              :     }
    4737              : 
    4738        20917 :     state.dataSolarShading->OverlapStatus = PartialOverlap;
    4739        20917 :     int NV1 = state.dataSolarShading->HCNV(NS1); // Number of vertices of figure NS1
    4740        20917 :     int NV2 = state.dataSolarShading->HCNV(NS2); // Number of vertices of figure NS2
    4741        20917 :     int NV3 = 0;                                 // Number of vertices of figure NS3 (the overlap of NS1 and NS2)
    4742        20917 :     int NIN1 = 0;                                // Number of vertices of NS1 within NS2
    4743        20917 :     int NIN2 = 0;                                // Number of vertices of NS2 within NS1
    4744              : 
    4745        20917 :     if (!state.dataSysVars->SutherlandHodgman) {
    4746            0 :         INCLOS(state, NS1, NV1, NS2, NV2, NV3, NIN1); // Find vertices of NS1 within NS2.
    4747              : 
    4748            0 :         if (NIN1 >= NV1) {
    4749              : 
    4750            0 :             state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
    4751              : 
    4752              :         } else {
    4753              : 
    4754            0 :             INCLOS(state, NS2, NV2, NS1, NV1, NV3, NIN2); // Find vertices of NS2 within NS1.
    4755              : 
    4756            0 :             if (NIN2 >= NV2) {
    4757              : 
    4758            0 :                 state.dataSolarShading->OverlapStatus = SecondSurfWithinFirst;
    4759              : 
    4760              :             } else {
    4761              : 
    4762            0 :                 INTCPT(state, NV1, NV2, NV3, NS1, NS2); // Find intercepts of NS1 & NS2.
    4763              : 
    4764            0 :                 if (NV3 < 3) { // Overlap must have 3 or more vertices
    4765            0 :                     state.dataSolarShading->OverlapStatus = NoOverlap;
    4766            0 :                     return;
    4767              :                 }
    4768              :             }
    4769              :         }
    4770              : 
    4771              :     } else {
    4772              :         // simple polygon clipping
    4773        20917 :         CLIPPOLY(state, NS1, NS2, NV1, NV2, NV3);
    4774              :     }
    4775              : 
    4776        20917 :     if (NV3 < state.dataSolarShading->MaxHCV) {
    4777              : 
    4778        20917 :         if (!state.dataSysVars->SutherlandHodgman) {
    4779            0 :             ORDER(state, NV3, NS3); // Put vertices in clockwise order.
    4780              :         } else {
    4781        20917 :             assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    4782        20917 :             int l = state.dataSolarShading->HCX.index(NS3, 1);
    4783        79830 :             for (int N = 1; N <= NV3; ++N, ++l) {
    4784        58913 :                 state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XTEMP(N)); // [ l ] == ( N, NS3 )
    4785        58913 :                 state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YTEMP(N));
    4786              :             }
    4787              :         }
    4788              : 
    4789        20917 :         HTRANS0(state, NS3, NV3); // Determine h.c. values of sides.
    4790              :         // Skip overlaps of negligible area.
    4791              : 
    4792        20917 :         if (std::abs(state.dataSolarShading->HCAREA(NS3)) * HCMULT < std::abs(state.dataSolarShading->HCAREA(NS1))) {
    4793         6406 :             state.dataSolarShading->OverlapStatus = NoOverlap;
    4794              :         } else {
    4795        14511 :             if (state.dataSolarShading->HCAREA(NS1) * state.dataSolarShading->HCAREA(NS2) > 0.0) {
    4796         2221 :                 state.dataSolarShading->HCAREA(NS3) = -state.dataSolarShading->HCAREA(NS3); // Determine sign of area of overlap
    4797              :             }
    4798        14511 :             Real64 const HCT_1 = state.dataSolarShading->HCT(NS1);
    4799        14511 :             Real64 const HCT_2 = state.dataSolarShading->HCT(NS2);
    4800        14511 :             if (HCT_2 == 1.0 || HCT_1 == 1.0) {
    4801        13851 :                 state.dataSolarShading->HCT(NS3) = HCT_1 * HCT_2;
    4802              :             } else {
    4803              :                 // Determine transmission of overlap which corrects for prior shadows
    4804              :                 // The resulting transmission of overlapping shadows is HCT_1 * HCT_2
    4805              :                 // Shadows with HCT_1 and HCT_2 have already been applied in the overlapping area
    4806              :                 // so the correction is the difference between (HCT_1+HCT_2) and (HCT_1*HCT_2)
    4807          660 :                 state.dataSolarShading->HCT(NS3) = (HCT_1 + HCT_2) - HCT_1 * HCT_2;
    4808              :             }
    4809              :         }
    4810              : 
    4811              :     } else {
    4812              : 
    4813            0 :         state.dataSolarShading->OverlapStatus = TooManyVertices;
    4814              : 
    4815            0 :         if (!state.dataSolarShading->TooManyVerticesMessage && !state.dataGlobal->DisplayExtraWarnings) {
    4816            0 :             ShowWarningError(state,
    4817            0 :                              format("DeterminePolygonOverlap: Too many vertices [>{}] detected in an overlap calculation. Use "
    4818              :                                     "Output:Diagnostics,DisplayExtraWarnings; for more details.",
    4819            0 :                                     state.dataSolarShading->MaxHCV));
    4820            0 :             state.dataSolarShading->TooManyVerticesMessage = true;
    4821              :         }
    4822              : 
    4823            0 :         if (state.dataGlobal->DisplayExtraWarnings) {
    4824            0 :             state.dataSolarShading->TrackTooManyVertices.redimension(++state.dataSolarShading->NumTooManyVertices);
    4825            0 :             state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex1 =
    4826            0 :                 state.dataSolarShading->CurrentShadowingSurface;
    4827            0 :             state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex2 =
    4828            0 :                 state.dataSolarShading->CurrentSurfaceBeingShadowed;
    4829              :         }
    4830              :     }
    4831              : }
    4832              : 
    4833         1838 : void CalcPerSolarBeam(EnergyPlusData &state,
    4834              :                       Real64 const AvgEqOfTime,       // Average value of Equation of Time for period
    4835              :                       Real64 const AvgSinSolarDeclin, // Average value of Sine of Solar Declination for period
    4836              :                       Real64 const AvgCosSolarDeclin  // Average value of Cosine of Solar Declination for period
    4837              : )
    4838              : {
    4839              : 
    4840              :     // SUBROUTINE INFORMATION:
    4841              :     //       AUTHOR         Legacy Code
    4842              :     //       DATE WRITTEN
    4843              :     //       MODIFIED       BG, Nov 2012 - Timestep solar.  DetailedSolarTimestepIntegration
    4844              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4845              : 
    4846              :     // PURPOSE OF THIS SUBROUTINE:
    4847              :     // This subroutine manages computation of solar gain multipliers for beam radiation.  These
    4848              :     // are calculated for a period of days depending on the input "Shadowing Calculations".
    4849              : 
    4850              :     // REFERENCES:
    4851              :     // BLAST/IBLAST code, original author George Walton
    4852              : 
    4853              :     // Using/Aliasing
    4854              : 
    4855              :     using WindowComplexManager::InitComplexWindows;
    4856              :     using WindowComplexManager::UpdateComplexWindows;
    4857              : 
    4858              :     int iHour; // Hour index number
    4859              :     int TS;    // TimeStep Loop Countergit
    4860              : 
    4861         1838 :     auto &s_surf = state.dataSurface;
    4862              : 
    4863         1838 :     if (state.dataSolarShading->InitComplexOnce) {
    4864          106 :         InitComplexWindows(state);
    4865              :     }
    4866         1838 :     state.dataSolarShading->InitComplexOnce = false;
    4867              : 
    4868         1838 :     if (state.dataGlobal->KickOffSizing || state.dataGlobal->KickOffSimulation) {
    4869          262 :         return; // Skip solar calcs for these Initialization steps.
    4870              :     }
    4871              : 
    4872              : #ifdef EP_Count_Calls
    4873              :     ++state.dataTimingsData->NumCalcPerSolBeam_Calls;
    4874              : #endif
    4875              : 
    4876              :     // Initialize some values for the appropriate period
    4877         1576 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4878          549 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4879          685 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4880          359 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    4881          359 :                 int firstSurf = thisSpace.OpaqOrIntMassSurfaceFirst;
    4882          359 :                 int lastSurf = thisSpace.OpaqOrIntMassSurfaceLast;
    4883         2252 :                 for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4884         1893 :                     s_surf->SurfOpaqAO(surfNum) = 0.0;
    4885              :                 }
    4886          359 :                 firstSurf = thisSpace.HTSurfaceFirst;
    4887          359 :                 lastSurf = thisSpace.HTSurfaceLast;
    4888         2363 :                 for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4889         2004 :                     state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
    4890              :                 }
    4891         8975 :                 for (int hour = 1; hour <= 24; ++hour) {
    4892        56712 :                     for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4893        48096 :                         state.dataHeatBal->SurfSunlitFracHR(hour, surfNum) = 0.0;
    4894        48096 :                         state.dataHeatBal->SurfCosIncAngHR(hour, surfNum) = 0.0;
    4895              :                     }
    4896              :                 }
    4897         8975 :                 for (int hour = 1; hour <= 24; ++hour) {
    4898        53784 :                     for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
    4899       294648 :                         for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4900       249480 :                             state.dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum) = 0.0;
    4901       249480 :                             state.dataHeatBal->SurfCosIncAng(hour, timestep, surfNum) = 0.0;
    4902       249480 :                             state.dataHeatBal->SurfSunlitFracWithoutReveal(hour, timestep, surfNum) = 0.0;
    4903              :                         }
    4904              :                     }
    4905              :                 }
    4906         8975 :                 for (int hour = 1; hour <= 24; ++hour) {
    4907        53784 :                     for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
    4908       948528 :                         for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
    4909      5892960 :                             for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4910      4989600 :                                 state.dataHeatBal->SurfWinBackSurfaces(hour, timestep, backSurfNum, surfNum) = 0.0;
    4911      4989600 :                                 state.dataHeatBal->SurfWinOverlapAreas(hour, timestep, backSurfNum, surfNum) = 0.0;
    4912              :                             }
    4913              :                         }
    4914              :                     } // for (timestep)
    4915              :                 } // for (hour)
    4916          326 :             } // for (spaceNum)
    4917              :         } // for (zoneNum)
    4918              : 
    4919         2270 :         for (auto &e : s_surf->SurfaceWindow) {
    4920         2047 :             std::fill(e.OutProjSLFracMult.begin(), e.OutProjSLFracMult.end(), 1.0);
    4921         2047 :             std::fill(e.InOutProjSLFracMult.begin(), e.InOutProjSLFracMult.end(), 1.0);
    4922          223 :         }
    4923              :     } else {
    4924         2705 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4925         2704 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4926         1352 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    4927         1352 :                 int const firstSurf = thisSpace.HTSurfaceFirst;
    4928         1352 :                 int const lastSurf = thisSpace.HTSurfaceLast;
    4929         5418 :                 for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4930         4066 :                     state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
    4931         4066 :                     s_surf->SurfOpaqAO(surfNum) = 0.0;
    4932         4066 :                     state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
    4933         4066 :                     state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
    4934         4066 :                     state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
    4935         4066 :                     state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
    4936         4066 :                     state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
    4937              :                 }
    4938        28392 :                 for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
    4939       108360 :                     for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4940        81320 :                         state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
    4941        81320 :                         state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
    4942              :                     }
    4943              :                 }
    4944         1352 :             }
    4945              :         }
    4946              : 
    4947         5434 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    4948         4081 :             s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
    4949         4081 :             s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
    4950              :         }
    4951              :     }
    4952              : 
    4953         1576 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4954         5575 :         for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours
    4955        34560 :             for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
    4956        29208 :                 FigureSunCosines(state, iHour, TS, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
    4957              :             }
    4958              :         }
    4959              :     } else {
    4960         1353 :         FigureSunCosines(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
    4961              :     }
    4962              :     // Initialize/update the Complex Fenestration geometry and optical properties
    4963         1576 :     UpdateComplexWindows(state);
    4964         1576 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4965         5575 :         for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours.
    4966        34560 :             for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
    4967        29208 :                 FigureSolarBeamAtTimestep(state, iHour, TS);
    4968              :             } // TimeStep Loop
    4969              :         } // Hour Loop
    4970              :     } else {
    4971         1353 :         FigureSolarBeamAtTimestep(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    4972              :     }
    4973              : }
    4974              : 
    4975        30561 : void FigureSunCosines(EnergyPlusData &state,
    4976              :                       int const iHour,
    4977              :                       int const iTimeStep,
    4978              :                       Real64 const EqOfTime,       // value of Equation of Time for period
    4979              :                       Real64 const SinSolarDeclin, // value of Sine of Solar Declination for period
    4980              :                       Real64 const CosSolarDeclin  // value of Cosine of Solar Declination for period
    4981              : )
    4982              : {
    4983              : 
    4984              :     // SUBROUTINE INFORMATION:
    4985              :     //       AUTHOR         B. Griffith
    4986              :     //       DATE WRITTEN   October 2012
    4987              :     //       MODIFIED       na
    4988              :     //       RE-ENGINEERED  na
    4989              : 
    4990              :     // PURPOSE OF THIS SUBROUTINE:
    4991              :     // Determine solar position.  Default for sun below horizon.
    4992              : 
    4993              :     // METHODOLOGY EMPLOYED:
    4994              :     // Given hour, timestep, equation of time, solar declination sine, and solar declination cosine,
    4995              :     // determine sun directions for use elsewhere
    4996              : 
    4997              :     // Using/Aliasing
    4998              : 
    4999              :     Real64 CurrentTime; // Current Time for passing to Solar Position Routine
    5000              : 
    5001        30561 :     auto &s_surf = state.dataSurface;
    5002              : 
    5003        30561 :     if (state.dataGlobal->TimeStepsInHour != 1) {
    5004        30249 :         CurrentTime = double(iHour - 1) + double(iTimeStep) * (state.dataGlobal->TimeStepZone);
    5005              :     } else {
    5006          312 :         CurrentTime = double(iHour) + state.dataEnvrn->TS1TimeOffset;
    5007              :     }
    5008        30561 :     SUN4(state, CurrentTime, EqOfTime, SinSolarDeclin, CosSolarDeclin);
    5009              : 
    5010              :     // Save hourly values for use in DaylightingManager
    5011        30561 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    5012        29208 :         if (iTimeStep == state.dataGlobal->TimeStepsInHour) {
    5013         5328 :             s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
    5014              :         }
    5015              :     } else {
    5016         1353 :         s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
    5017              :     }
    5018              :     // Save timestep values for use in WindowComplexManager
    5019        30561 :     state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour) = state.dataSolarShading->SUNCOS;
    5020        30561 : }
    5021              : 
    5022        30582 : void FigureSolarBeamAtTimestep(EnergyPlusData &state, int const iHour, int const iTimeStep)
    5023              : {
    5024              : 
    5025              :     // SUBROUTINE INFORMATION:
    5026              :     //       AUTHOR         B.Griffith, derived from CalcPerSolarBeam, Legacy and Lawrie.
    5027              :     //       DATE WRITTEN   October 2012
    5028              :     //       MODIFIED       na
    5029              :     //       RE-ENGINEERED  na
    5030              : 
    5031              :     // PURPOSE OF THIS SUBROUTINE:
    5032              :     // This subroutine computes solar gain multipliers for beam solar
    5033              : 
    5034              :     using DataSystemVariables::ShadingMethod;
    5035              : 
    5036              :     Real64 SurfArea;        // Surface area. For walls, includes all window frame areas.
    5037              :     Real64 Fac1WoShdg;      // Intermediate calculation factor, without shading
    5038              :     Real64 Fac1WithShdg;    // Intermediate calculation factor, with shading
    5039              :     Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
    5040              : 
    5041        30582 :     auto &s_surf = state.dataSurface;
    5042              : 
    5043              :     // Recover the sun direction from the array stored in previous loop
    5044        30582 :     state.dataSolarShading->SUNCOS = state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour);
    5045              : 
    5046        30582 :     state.dataSolarShading->SurfSunCosTheta = 0.0;
    5047              : 
    5048        30582 :     if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) {
    5049        15503 :         return;
    5050              :     }
    5051              : 
    5052       143972 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    5053       257786 :         state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
    5054       128893 :                                                            state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
    5055       128893 :                                                            state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
    5056       128893 :         if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    5057       127181 :             if (iTimeStep == state.dataGlobal->TimeStepsInHour) {
    5058        24518 :                 state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
    5059              :             }
    5060              :         } else {
    5061         1712 :             state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
    5062              :         }
    5063       128893 :         state.dataHeatBal->SurfCosIncAng(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
    5064              :     }
    5065              : 
    5066        30157 :     if ((state.dataSysVars->shadingMethod == ShadingMethod::Scheduled || state.dataSysVars->shadingMethod == ShadingMethod::Imported) &&
    5067        30157 :         !state.dataGlobal->DoingSizing && state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
    5068           10 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    5069            9 :             auto &surf = s_surf->Surface(SurfNum);
    5070            9 :             if (surf.SurfSchedExternalShadingFrac) {
    5071            1 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = surf.surfExternalShadingSched->getHrTsVal(state, iHour, iTimeStep);
    5072              :             } else {
    5073            8 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
    5074              :             }
    5075              :         }
    5076              :     } else {
    5077        15078 :         SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
    5078       143962 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    5079       128884 :             if (s_surf->Surface(SurfNum).Area >= 1.e-10) {
    5080       128884 :                 SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
    5081       128884 :                 if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    5082       127172 :                     if (iTimeStep == state.dataGlobal->TimeStepsInHour) {
    5083        24518 :                         state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    5084              :                     }
    5085              :                 } else {
    5086         1712 :                     state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    5087              :                 }
    5088       128884 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    5089       128884 :                 if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) < 1.e-5) {
    5090        84982 :                     state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 0.0;
    5091              :                 }
    5092              :             }
    5093              :             // Added check
    5094       128884 :             if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 1.0) {
    5095            0 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
    5096              :             }
    5097              :         }
    5098              :     }
    5099              :     //   Note -- if not the below, values are set in SkyDifSolarShading routine (constant for simulation)
    5100        15096 :     if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
    5101           17 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
    5102          148 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    5103          131 :             state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) = 0.;
    5104          131 :             state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) = 0.;
    5105          131 :             state.dataSolarShading->SurfWithShdgHoriz(SurfNum) = 0.;
    5106          131 :             state.dataSolarShading->SurfWoShdgHoriz(SurfNum) = 0.;
    5107              :         }
    5108              : 
    5109          119 :         for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
    5110          102 :             state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
    5111              : 
    5112         2550 :             for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
    5113         2448 :                 state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
    5114         2448 :                 state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
    5115              : 
    5116        21312 :                 for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
    5117        37728 :                     state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
    5118        18864 :                                                                        state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
    5119        18864 :                                                                        state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
    5120         2448 :                 }
    5121              : 
    5122         2448 :                 SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
    5123              : 
    5124        21312 :                 for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
    5125              : 
    5126        18864 :                     if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) {
    5127        10338 :                         continue;
    5128              :                     }
    5129              : 
    5130         8526 :                     Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
    5131         8526 :                     SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
    5132         8526 :                     if (SurfArea > Eps) {
    5133         8526 :                         FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    5134              :                     } else {
    5135            0 :                         FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
    5136              :                     }
    5137         8526 :                     Fac1WithShdg = Fac1WoShdg * FracIlluminated;
    5138         8526 :                     state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
    5139         8526 :                     state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
    5140              : 
    5141              :                     // Horizon region
    5142         8526 :                     if (IPhi == 0) {
    5143         1421 :                         state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
    5144         1421 :                         state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
    5145              :                     }
    5146         2448 :                 } // End of surface loop
    5147              :             } // End of Theta loop
    5148              :         } // End of Phi loop
    5149              : 
    5150          148 :         for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
    5151              :             // Original conditions:
    5152              :             // if (!s_surf->Surface(SurfNum).IsShadowing &&
    5153              :             //    (!s_surf->Surface(SurfNum).HeatTransSurf || !s_surf->Surface(SurfNum).ExtSolar))
    5154              :             //    continue;
    5155              : 
    5156          131 :             if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
    5157           95 :                 state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
    5158           95 :                     (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
    5159              :             } else {
    5160           36 :                 state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
    5161           36 :                     (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
    5162              :             }
    5163          131 :             if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
    5164           95 :                 state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
    5165           95 :                     (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
    5166              :             } else {
    5167           36 :                 state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
    5168           36 :                     (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
    5169              :             }
    5170           17 :         }
    5171              : 
    5172              :         //  ! Get IR view factors. An exterior surface can receive IR radiation from
    5173              :         //  ! sky, ground or shadowing surfaces. Assume shadowing surfaces have same
    5174              :         //  ! temperature as outside air (and therefore same temperature as ground),
    5175              :         //  ! so that the view factor to these shadowing surfaces can be included in
    5176              :         //  ! the ground view factor. Sky IR is assumed to be isotropic and shadowing
    5177              :         //  ! surfaces are assumed to be opaque to IR so they totally "shade" IR from
    5178              :         //  ! sky or ground.
    5179              : 
    5180              :         //  DO SurfNum = 1,TotSurfaces
    5181              :         //    Surface(SurfNum)%ViewFactorSkyIR = Surface(SurfNum)%ViewFactorSkyIR * DifShdgRatioIsoSky(SurfNum,IHOUR,TS)
    5182              :         //    Surface(SurfNum)%ViewFactorGroundIR = 1.0 - Surface(SurfNum)%ViewFactorSkyIR
    5183              :         //  END DO
    5184              : 
    5185              :     } // test for shading surfaces
    5186              : 
    5187        15102 :     for (int SurfNum : s_surf->AllExtSolWinWithFrameSurfaceList) {
    5188              :         // For exterior windows with frame/divider that are partially or fully sunlit,
    5189              :         // correct SunlitFrac due to shadowing of frame and divider projections onto window glass.
    5190              :         // Note: if SunlitFrac = 0.0 the window is either completely shaded or the sun is in back
    5191              :         // of the window; in either case, frame/divider shadowing doesn't have to be done.
    5192              : 
    5193           23 :         if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 0.0) {
    5194           17 :             CalcFrameDividerShadow(state, SurfNum, s_surf->Surface(SurfNum).FrameDivider, iHour);
    5195              :         }
    5196        15079 :     }
    5197              : }
    5198              : 
    5199          133 : void DetermineShadowingCombinations(EnergyPlusData &state)
    5200              : {
    5201              : 
    5202              :     // SUBROUTINE INFORMATION:
    5203              :     //       AUTHOR         From Legacy Code
    5204              :     //       DATE WRITTEN
    5205              :     //       MODIFIED       LKL; March 2002 -- another missing translation from BLAST's routine
    5206              :     //                      FCW; Jan 2003 -- removed line that prevented beam solar through interior windows
    5207              :     //       RE-ENGINEERED  Rick Strand; 1998
    5208              :     //                      Linda Lawrie; Oct 2000
    5209              : 
    5210              :     // PURPOSE OF THIS SUBROUTINE:
    5211              :     // This routine prepares a list of heat transfer surfaces and
    5212              :     // their possible shadowers which is used to direct the hourly
    5213              :     // calculation of shadows and sunlit areas.
    5214              : 
    5215              :     // METHODOLOGY EMPLOYED:
    5216              :     // As appropriate surfaces are identified, they are placed into the
    5217              :     // ShadowComb data structure (module level) with the accompanying lists
    5218              :     // of other surface numbers.
    5219              : 
    5220              :     // REFERENCES:
    5221              :     // BLAST/IBLAST code, original author George Walton
    5222              : 
    5223              :     // Using/Aliasing
    5224              :     using namespace DataErrorTracking;
    5225              : 
    5226          133 :     Array1D_int GSS;             // List of shadowing surfaces numbers for a receiving surface
    5227          133 :     Array1D_int BKS;             // List of back surface numbers for a receiving surface
    5228          133 :     Array1D_int SBS;             // List of subsurfaces for a receiving surface
    5229              :     bool CannotShade;            // TRUE if subsurface cannot shade receiving surface
    5230              :     bool HasWindow;              // TRUE if a window is present on receiving surface
    5231              :     Real64 ZMIN;                 // Lowest point on the receiving surface
    5232              :     int BackSurfaceNumber;       // Back surface number
    5233              :     int HTS;                     // Heat transfer surface number for a receiving surface
    5234              :     int GRSNR;                   // Receiving surface number
    5235              :     int GSSNR;                   // Shadowing surface number
    5236              :     int SBSNR;                   // Subsurface number
    5237              :     int NBKS;                    // Number of back surfaces for a receiving surface
    5238              :     int NGSS;                    // Number of shadowing surfaces for a receiving surface
    5239              :     int NSBS;                    // Number of subsurfaces for a receiving surface
    5240              :     bool ShadowingSurf;          // True if a receiving surface is a shadowing surface
    5241          133 :     Array1D_bool CastingSurface; // tracking during setup of ShadowComb
    5242              : 
    5243          133 :     auto &s_surf = state.dataSurface;
    5244              : 
    5245              : #ifdef EP_Count_Calls
    5246              :     ++state.dataTimingsData->NumDetShadowCombs_Calls;
    5247              : #endif
    5248              : 
    5249          133 :     state.dataShadowComb->ShadowComb.dimension(s_surf->TotSurfaces, ShadowingCombinations{}); // Set all elements to default constructed state
    5250              : 
    5251          133 :     CastingSurface.dimension(s_surf->TotSurfaces, false);
    5252              : 
    5253          133 :     state.dataSolarShading->HCA.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5254          133 :     state.dataSolarShading->HCB.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5255          133 :     state.dataSolarShading->HCC.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5256          133 :     state.dataSolarShading->HCX.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5257          133 :     state.dataSolarShading->HCY.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5258          133 :     state.dataSolarShading->HCAREA.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
    5259          133 :     state.dataSolarShading->HCNS.dimension(2 * state.dataSolarShading->MaxHCS, 0);
    5260          133 :     state.dataSolarShading->HCNV.dimension(2 * state.dataSolarShading->MaxHCS, 0);
    5261          133 :     state.dataSolarShading->HCT.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
    5262              : 
    5263          133 :     GSS.dimension(state.dataSolarShading->MaxGSS, 0);
    5264          133 :     BKS.dimension(state.dataSolarShading->MaxGSS, 0);
    5265          133 :     SBS.dimension(state.dataSolarShading->MaxGSS, 0);
    5266              : 
    5267          133 :     state.dataSolarShading->penumbraIDs.clear();
    5268              : 
    5269          133 :     HTS = 0;
    5270              : 
    5271              :     // Check every surface as a possible shadow receiving surface ("RS" = receiving surface).
    5272          133 :     if (state.dataEnvrn->IgnoreSolarRadiation) {
    5273            0 :         return;
    5274              :     }
    5275              : 
    5276         1108 :     for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) { // Loop through all surfaces (looking for potential receiving surfaces)...
    5277              : 
    5278          975 :         ShadowingSurf = s_surf->Surface(GRSNR).IsShadowing;
    5279          975 :         NGSS = 0;
    5280          975 :         NSBS = 0;
    5281          975 :         NBKS = 0;
    5282              : 
    5283          975 :         if (!ShadowingSurf && !s_surf->Surface(GRSNR).HeatTransSurf) {
    5284            2 :             continue;
    5285              :         }
    5286          973 :         HTS = GRSNR;
    5287              : 
    5288              : #ifndef EP_NO_OPENGL
    5289          973 :         if (state.dataSolarShading->penumbra) {
    5290            0 :             bool skipSurface = s_surf->Surface(GRSNR).MirroredSurf;
    5291              :             // Penumbra doesn't need mirrored surfaces TODO: Don't bother creating them in the first place?
    5292              : 
    5293              :             // Skip interior surfaces if the other side has already been added to penumbra
    5294            0 :             if (s_surf->Surface(GRSNR).ExtBoundCond > 0) {
    5295            0 :                 if (s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond) >= 0) {
    5296            0 :                     s_surf->SurfPenumbraID(GRSNR) = s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond);
    5297            0 :                     skipSurface = true;
    5298              :                 }
    5299              :             }
    5300              : 
    5301            0 :             if (!skipSurface) {
    5302              :                 // Add surfaces to penumbra...
    5303            0 :                 Penumbra::Polygon poly;
    5304              : 
    5305            0 :                 if (s_surf->Surface(GRSNR).Reveal > 0.0) {
    5306            0 :                     Real64 R = s_surf->Surface(GRSNR).Reveal;
    5307            0 :                     auto &norm = s_surf->Surface(GRSNR).NewellSurfaceNormalVector;
    5308            0 :                     auto &v = s_surf->Surface(GRSNR).Vertex;
    5309            0 :                     for (unsigned i = 0; i < v.size(); ++i) {
    5310            0 :                         poly.push_back(v[i].x);
    5311            0 :                         poly.push_back(v[i].y);
    5312            0 :                         poly.push_back(v[i].z);
    5313              : 
    5314            0 :                         Vector vPrev;
    5315            0 :                         if (i == 0) {
    5316            0 :                             vPrev = v[v.size() - 1];
    5317              :                         } else {
    5318            0 :                             vPrev = v[i - 1];
    5319              :                         }
    5320              : 
    5321            0 :                         Penumbra::Polygon rPoly; // Reveal surface
    5322            0 :                         rPoly.push_back(v[i].x);
    5323            0 :                         rPoly.push_back(v[i].y);
    5324            0 :                         rPoly.push_back(v[i].z);
    5325              : 
    5326            0 :                         rPoly.push_back(v[i].x + norm.x * R);
    5327            0 :                         rPoly.push_back(v[i].y + norm.y * R);
    5328            0 :                         rPoly.push_back(v[i].z + norm.z * R);
    5329              : 
    5330            0 :                         rPoly.push_back(vPrev.x + norm.x * R);
    5331            0 :                         rPoly.push_back(vPrev.y + norm.y * R);
    5332            0 :                         rPoly.push_back(vPrev.z + norm.z * R);
    5333              : 
    5334            0 :                         rPoly.push_back(vPrev.x);
    5335            0 :                         rPoly.push_back(vPrev.y);
    5336            0 :                         rPoly.push_back(vPrev.z);
    5337              : 
    5338            0 :                         Penumbra::Surface rSurf(rPoly, fmt::format("{} reveal {}", s_surf->Surface(GRSNR).Name, i));
    5339            0 :                         state.dataSolarShading->penumbra->add_surface(rSurf);
    5340            0 :                     }
    5341              :                 } else {
    5342            0 :                     for (auto const &v : s_surf->Surface(GRSNR).Vertex) {
    5343            0 :                         poly.push_back(v.x);
    5344            0 :                         poly.push_back(v.y);
    5345            0 :                         poly.push_back(v.z);
    5346              :                     }
    5347              :                 }
    5348            0 :                 Penumbra::Surface pSurf(poly, s_surf->Surface(GRSNR).Name);
    5349              : 
    5350              :                 // Punch holes for subsurfaces
    5351            0 :                 if (s_surf->Surface(GRSNR).BaseSurf == GRSNR) { // Only look for subsurfaces on base surfaces
    5352            0 :                     for (int subSurface = 1; subSurface <= s_surf->TotSurfaces; ++subSurface) {
    5353            0 :                         if (s_surf->Surface(subSurface).BaseSurf != GRSNR) {
    5354            0 :                             continue; // Ignore subsurfaces of other surfaces
    5355              :                         }
    5356            0 :                         if (!s_surf->Surface(subSurface).HeatTransSurf) {
    5357            0 :                             continue; // Skip non heat transfer subsurfaces
    5358              :                         }
    5359            0 :                         if (subSurface == GRSNR) {
    5360            0 :                             continue; // Surface itself cannot be its own subsurface
    5361              :                         }
    5362              : 
    5363            0 :                         Penumbra::Polygon subPoly;
    5364            0 :                         if (s_surf->Surface(subSurface).Reveal > 0.0) {
    5365            0 :                             Real64 R = s_surf->Surface(subSurface).Reveal;
    5366            0 :                             auto &norm = s_surf->Surface(subSurface).NewellSurfaceNormalVector;
    5367            0 :                             for (auto const &v : s_surf->Surface(subSurface).Vertex) {
    5368            0 :                                 subPoly.push_back(v.x + norm.x * R);
    5369            0 :                                 subPoly.push_back(v.y + norm.y * R);
    5370            0 :                                 subPoly.push_back(v.z + norm.z * R);
    5371              :                             }
    5372              :                         } else {
    5373            0 :                             for (auto const &v : s_surf->Surface(subSurface).Vertex) {
    5374            0 :                                 subPoly.push_back(v.x);
    5375            0 :                                 subPoly.push_back(v.y);
    5376            0 :                                 subPoly.push_back(v.z);
    5377              :                             }
    5378              :                         }
    5379              : 
    5380            0 :                         pSurf.add_hole(subPoly);
    5381            0 :                     }
    5382              :                 }
    5383            0 :                 s_surf->SurfPenumbraID(GRSNR) = state.dataSolarShading->penumbra->add_surface(pSurf);
    5384            0 :                 state.dataSolarShading->penumbraIDs.push_back(s_surf->SurfPenumbraID(GRSNR));
    5385            0 :             }
    5386              :         }
    5387              : #endif
    5388              : 
    5389          973 :         if (!ShadowingSurf && !s_surf->Surface(GRSNR).ExtSolar) {
    5390          302 :             continue; // Skip surfaces with no external solar
    5391              :         }
    5392              : 
    5393          671 :         if (!ShadowingSurf && s_surf->Surface(GRSNR).BaseSurf != GRSNR) { // Skip subsurfaces (SBS)
    5394           70 :             continue;
    5395              :         }
    5396              : 
    5397              :         // Get the lowest point of receiving surface
    5398          601 :         ZMIN = minval(s_surf->Surface(GRSNR).Vertex, &Vector::z);
    5399              : 
    5400              :         // Check every surface as a possible shadow casting surface ("SS" = shadow sending)
    5401          601 :         NGSS = 0;
    5402          601 :         if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) { // Except when doing simplified exterior shadowing.
    5403              : 
    5404         5485 :             for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces, looking for ones that could shade GRSNR
    5405              : 
    5406         5090 :                 if (GSSNR == GRSNR) {
    5407          395 :                     continue; // Receiving surface cannot shade itself
    5408              :                 }
    5409         4695 :                 if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR)) {
    5410           63 :                     continue; // A heat transfer subsurface of a receiving surface
    5411              :                 }
    5412              :                 // cannot shade the receiving surface
    5413         4632 :                 if (ShadowingSurf) {
    5414              :                     // If receiving surf is a shadowing surface exclude matching shadow surface as sending surface
    5415              :                     // IF((GSSNR == GRSNR+1 .AND. Surface(GSSNR)%Name(1:3) == 'Mir').OR. &
    5416              :                     //   (GSSNR == GRSNR-1 .AND. Surface(GRSNR)%Name(1:3) == 'Mir')) CYCLE
    5417         1817 :                     if (((GSSNR == GRSNR + 1) && s_surf->Surface(GSSNR).MirroredSurf) ||
    5418          893 :                         ((GSSNR == GRSNR - 1) && s_surf->Surface(GRSNR).MirroredSurf)) {
    5419           62 :                         continue;
    5420              :                     }
    5421              :                 }
    5422              : 
    5423         4570 :                 if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
    5424              : 
    5425            0 :                     ++NGSS;
    5426            0 :                     if (NGSS > state.dataSolarShading->MaxGSS) {
    5427            0 :                         GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
    5428              :                     }
    5429            0 :                     GSS(NGSS) = GSSNR;
    5430              : 
    5431         8712 :                 } else if ((s_surf->Surface(GSSNR).BaseSurf == 0) ||
    5432         4142 :                            ((s_surf->Surface(GSSNR).BaseSurf == GSSNR) &&
    5433         3610 :                             ((s_surf->Surface(GSSNR).ExtBoundCond == ExternalEnvironment) ||
    5434         1472 :                              s_surf->Surface(GSSNR).ExtBoundCond ==
    5435              :                                  OtherSideCondModeledExt))) { // Detached shadowing surface or | any other base surface
    5436              :                     // exposed to outside environment
    5437              : 
    5438         2566 :                     CHKGSS(state, GRSNR, GSSNR, ZMIN, CannotShade); // Check to see if this can shade the receiving surface
    5439         2566 :                     if (!CannotShade) {                             // Update the shadowing surface data if shading is possible
    5440          126 :                         ++NGSS;
    5441          126 :                         if (NGSS > state.dataSolarShading->MaxGSS) {
    5442            0 :                             GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
    5443              :                         }
    5444          126 :                         GSS(NGSS) = GSSNR;
    5445              :                     }
    5446              :                 }
    5447              : 
    5448              :             } // ...end of surfaces DO loop (GSSNR)
    5449              :         } else { // Simplified Distribution -- still check for Shading Subsurfaces
    5450              : 
    5451         1483 :             for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces (looking for surfaces which could shade GRSNR) ...
    5452              : 
    5453         1277 :                 if (GSSNR == GRSNR) {
    5454          206 :                     continue; // Receiving surface cannot shade itself
    5455              :                 }
    5456         1071 :                 if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR)) {
    5457            7 :                     continue; // Skip heat transfer subsurfaces of receiving surface
    5458              :                 }
    5459         1064 :                 if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
    5460            0 :                     ++NGSS;
    5461            0 :                     if (NGSS > state.dataSolarShading->MaxGSS) {
    5462            0 :                         GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
    5463              :                     }
    5464            0 :                     GSS(NGSS) = GSSNR;
    5465              :                 }
    5466              :             }
    5467              : 
    5468              :         } // ...end of check for simplified solar distribution
    5469              : 
    5470              :         // Check every surface as a receiving subsurface of the receiving surface
    5471          601 :         NSBS = 0;
    5472          601 :         HasWindow = false;
    5473              :         // legacy: IF (OSENV(HTS) > 10) WINDOW=.TRUE. -->Note: WINDOW was set true for roof ponds, solar walls, or other zones
    5474         6968 :         for (SBSNR = 1; SBSNR <= s_surf->TotSurfaces; ++SBSNR) { // Loop through the surfaces yet again (looking for subsurfaces of GRSNR)...
    5475              : 
    5476         6367 :             if (!s_surf->Surface(SBSNR).HeatTransSurf) {
    5477          552 :                 continue; // Skip non heat transfer subsurfaces
    5478              :             }
    5479         5815 :             if (SBSNR == GRSNR) {
    5480          539 :                 continue; // Surface itself cannot be its own subsurface
    5481              :             }
    5482         5276 :             if (s_surf->Surface(SBSNR).BaseSurf != GRSNR) {
    5483         5206 :                 continue; // Ignore subsurfaces of other surfaces and other surfaces
    5484              :             }
    5485              : 
    5486           70 :             if (state.dataConstruction->Construct(s_surf->Surface(SBSNR).Construction).TransDiff > 0.0) {
    5487           45 :                 HasWindow = true; // Check for window
    5488              :             }
    5489           70 :             CHKSBS(state, HTS, GRSNR, SBSNR); // Check that the receiving surface completely encloses the subsurface;
    5490              :             // severe error if not
    5491           70 :             ++NSBS;
    5492           70 :             if (NSBS > state.dataSolarShading->MaxSBS) {
    5493            0 :                 SBS.redimension(state.dataSolarShading->MaxSBS *= 2, 0);
    5494              :             }
    5495           70 :             SBS(NSBS) = SBSNR;
    5496              : 
    5497              :         } // ...end of surfaces DO loop (SBSNR)
    5498              : 
    5499              :         // Check every surface as a back surface
    5500          601 :         NBKS = 0;
    5501              :         //                                        Except for simplified
    5502              :         //                                        interior solar distribution,
    5503          601 :         if ((state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) &&
    5504              :             (HasWindow)) { // For full interior solar distribution | and a window present on base surface (GRSNR)
    5505              : 
    5506           76 :             for (BackSurfaceNumber = 1; BackSurfaceNumber <= s_surf->TotSurfaces;
    5507              :                  ++BackSurfaceNumber) { // Loop through surfaces yet again, looking for back surfaces to GRSNR
    5508              : 
    5509           69 :                 if (!s_surf->Surface(BackSurfaceNumber).HeatTransSurf) {
    5510            0 :                     continue; // Skip non-heat transfer surfaces
    5511              :                 }
    5512           69 :                 if (s_surf->Surface(BackSurfaceNumber).BaseSurf == GRSNR) {
    5513           14 :                     continue; // Skip subsurfaces of this GRSNR
    5514              :                 }
    5515           55 :                 if (BackSurfaceNumber == GRSNR) {
    5516            0 :                     continue; // A back surface cannot be GRSNR itself
    5517              :                 }
    5518           55 :                 if (s_surf->Surface(BackSurfaceNumber).SolarEnclIndex != s_surf->Surface(GRSNR).SolarEnclIndex) {
    5519           14 :                     continue; // Skip if back surface not in same solar enclosure
    5520              :                 }
    5521              : 
    5522           41 :                 if (s_surf->Surface(BackSurfaceNumber).Class == SurfaceClass::IntMass) {
    5523            0 :                     continue;
    5524              :                 }
    5525              : 
    5526              :                 // Following line removed 1/27/03 by FCW. Was in original code that didn't do beam solar transmitted through
    5527              :                 // interior windows. Was removed to allow such beam solar but then somehow was put back in.
    5528              :                 // IF (Surface(BackSurfaceNumber)%BaseSurf /= BackSurfaceNumber) CYCLE ! Not for subsurfaces of Back Surface
    5529              : 
    5530           41 :                 if (!state.dataSolarShading->penumbra) {
    5531           41 :                     CHKBKS(state, BackSurfaceNumber, GRSNR); // CHECK FOR CONVEX ZONE; severe error if not
    5532              :                 }
    5533           41 :                 ++NBKS;
    5534           41 :                 if (NBKS > state.dataSolarShading->MaxBKS) {
    5535            0 :                     BKS.redimension(state.dataSolarShading->MaxBKS *= 2, 0);
    5536              :                 }
    5537           41 :                 BKS(NBKS) = BackSurfaceNumber;
    5538              : 
    5539              :             } // ...end of surfaces DO loop (BackSurfaceNumber)
    5540              :         }
    5541              : 
    5542              :         // Put this into the ShadowComb data structure
    5543          601 :         state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf = true;
    5544          601 :         state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf = NGSS;
    5545          601 :         state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf = NBKS;
    5546          601 :         state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf = NSBS;
    5547          601 :         state.dataSolarShading->MaxDim = max(state.dataSolarShading->MaxDim, NGSS, NBKS, NSBS);
    5548              : 
    5549          601 :         state.dataShadowComb->ShadowComb(GRSNR).GenSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf});
    5550          601 :         state.dataShadowComb->ShadowComb(GRSNR).GenSurf(0) = 0;
    5551          601 :         if (state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf > 0) {
    5552           89 :             state.dataShadowComb->ShadowComb(GRSNR).GenSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf}) = GSS({1, NGSS});
    5553              :         }
    5554              : 
    5555          601 :         state.dataShadowComb->ShadowComb(GRSNR).BackSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf});
    5556          601 :         state.dataShadowComb->ShadowComb(GRSNR).BackSurf(0) = 0;
    5557          601 :         if (state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf > 0) {
    5558            7 :             state.dataShadowComb->ShadowComb(GRSNR).BackSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf}) = BKS({1, NBKS});
    5559              :         }
    5560              : 
    5561          601 :         state.dataShadowComb->ShadowComb(GRSNR).SubSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf});
    5562          601 :         state.dataShadowComb->ShadowComb(GRSNR).SubSurf(0) = 0;
    5563          601 :         if (state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf > 0) {
    5564           65 :             state.dataShadowComb->ShadowComb(GRSNR).SubSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf}) = SBS({1, NSBS});
    5565              :         }
    5566              : 
    5567              :     } // ...end of surfaces (GRSNR) DO loop
    5568              : 
    5569          133 :     GSS.deallocate();
    5570          133 :     SBS.deallocate();
    5571          133 :     BKS.deallocate();
    5572              : 
    5573          133 :     if (!state.dataSolarShading->penumbra) {
    5574          133 :         if (state.dataSolarShading->shd_stream) {
    5575          114 :             *state.dataSolarShading->shd_stream << "Shadowing Combinations\n";
    5576          114 :             if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    5577           41 :                 *state.dataSolarShading->shd_stream
    5578           41 :                     << "..Solar Distribution=Minimal Shadowing, Detached Shading will not be used in shadowing calculations\n";
    5579           73 :             } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullExterior) {
    5580           63 :                 if (s_surf->CalcSolRefl) {
    5581            0 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExteriorWithReflectionsFromExteriorSurfaces\n";
    5582              :                 } else {
    5583           63 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExterior\n";
    5584              :                 }
    5585           10 :             } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
    5586           10 :                 if (s_surf->CalcSolRefl) {
    5587            0 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExteriorWithReflectionsFromExteriorSurfaces\n";
    5588              :                 } else {
    5589           10 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExterior\n";
    5590              :                 }
    5591              :             } else {
    5592              :             }
    5593              : 
    5594          114 :             *state.dataSolarShading->shd_stream << "..In the following, only the first 10 reference surfaces will be shown.\n";
    5595          114 :             *state.dataSolarShading->shd_stream << "..But all surfaces are used in the calculations.\n";
    5596              : 
    5597          941 :             for (int HTSnum : s_surf->AllSurfaceListReportOrder) {
    5598          827 :                 *state.dataSolarShading->shd_stream << "==================================\n";
    5599          827 :                 if (state.dataShadowComb->ShadowComb(HTSnum).UseThisSurf) {
    5600          484 :                     if (s_surf->Surface(HTSnum).IsConvex) {
    5601          960 :                         *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
    5602          960 :                                                             << " is used as Receiving Surface in calculations and is convex.\n";
    5603              :                     } else {
    5604            8 :                         *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
    5605            8 :                                                             << " is used as Receiving Surface in calculations and is non-convex.\n";
    5606            4 :                         if (state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf > 0) {
    5607            2 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    5608            0 :                                 ShowWarningError(state,
    5609            0 :                                                  format("DetermineShadowingCombinations: Surface=\"{}\" is a receiving surface and is non-convex.",
    5610            0 :                                                         s_surf->Surface(HTSnum).Name));
    5611            0 :                                 ShowContinueError(state,
    5612              :                                                   "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5613              :                             } else {
    5614            2 :                                 ++state.dataErrTracking->TotalReceivingNonConvexSurfaces;
    5615              :                             }
    5616              :                         }
    5617              :                     }
    5618              :                 } else {
    5619          686 :                     *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
    5620          686 :                                                         << " is not used as Receiving Surface in calculations.\n";
    5621              :                 }
    5622          827 :                 *state.dataSolarShading->shd_stream << "Number of general casting surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf
    5623          827 :                                                     << '\n';
    5624          904 :                 for (NGSS = 1; NGSS <= state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf; ++NGSS) {
    5625           77 :                     if (NGSS <= 10) {
    5626           77 :                         *state.dataSolarShading->shd_stream
    5627           77 :                             << "..Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)).Name << '\n';
    5628              :                     }
    5629           77 :                     CastingSurface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)) = true;
    5630              :                 }
    5631          827 :                 *state.dataSolarShading->shd_stream << "Number of back surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf << '\n';
    5632          861 :                 for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf); ++NGSS) {
    5633           34 :                     *state.dataSolarShading->shd_stream
    5634           34 :                         << "...Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).BackSurf(NGSS)).Name << '\n';
    5635              :                 }
    5636          827 :                 *state.dataSolarShading->shd_stream << "Number of receiving sub surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf
    5637          827 :                                                     << '\n';
    5638          884 :                 for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf); ++NGSS) {
    5639           57 :                     *state.dataSolarShading->shd_stream
    5640           57 :                         << "....Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).SubSurf(NGSS)).Name << '\n';
    5641              :                 }
    5642          114 :             }
    5643              :         }
    5644              : 
    5645         1108 :         for (HTS = 1; HTS <= s_surf->TotSurfaces; ++HTS) {
    5646          975 :             if (CastingSurface(HTS) && !s_surf->Surface(HTS).IsConvex) {
    5647            2 :                 if (state.dataGlobal->DisplayExtraWarnings) {
    5648            0 :                     ShowSevereError(
    5649              :                         state,
    5650            0 :                         format("DetermineShadowingCombinations: Surface=\"{}\" is a casting surface and is non-convex.", s_surf->Surface(HTS).Name));
    5651            0 :                     ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5652              :                 } else {
    5653            2 :                     ++state.dataErrTracking->TotalCastingNonConvexSurfaces;
    5654              :                 }
    5655              :             }
    5656              :         }
    5657              : 
    5658          133 :         if (state.dataErrTracking->TotalReceivingNonConvexSurfaces > 0) {
    5659            6 :             ShowWarningMessage(state,
    5660            6 :                                format("DetermineShadowingCombinations: There are {} surfaces which are receiving surfaces and are non-convex.",
    5661            3 :                                       state.dataErrTracking->TotalReceivingNonConvexSurfaces));
    5662            6 :             ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5663            6 :             ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual warnings for each surface.");
    5664            3 :             state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalReceivingNonConvexSurfaces;
    5665              :         }
    5666              : 
    5667          133 :         if (state.dataErrTracking->TotalCastingNonConvexSurfaces > 0) {
    5668            6 :             ShowSevereMessage(state,
    5669            6 :                               format("DetermineShadowingCombinations: There are {} surfaces which are casting surfaces and are non-convex.",
    5670            3 :                                      state.dataErrTracking->TotalCastingNonConvexSurfaces));
    5671            6 :             ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5672            6 :             ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual severes for each surface.");
    5673            3 :             state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalCastingNonConvexSurfaces;
    5674              :         }
    5675              :     }
    5676              : 
    5677          133 :     CastingSurface.deallocate();
    5678              : 
    5679              : #ifndef EP_NO_OPENGL
    5680          133 :     if (state.dataSolarShading->penumbra && state.dataSolarShading->penumbra->get_number_of_surfaces() > 0) {
    5681            0 :         state.dataSolarShading->penumbra->set_model();
    5682              :     }
    5683              : #endif
    5684          133 : }
    5685              : 
    5686        33798 : void SHADOW(EnergyPlusData &state,
    5687              :             int const iHour, // Hour index
    5688              :             int const TS     // Time Step
    5689              : )
    5690              : {
    5691              : 
    5692              :     // SUBROUTINE INFORMATION:
    5693              :     //       AUTHOR         Legacy Code
    5694              :     //       DATE WRITTEN
    5695              :     //       MODIFIED       Nov 2003, FCW: modify to do shadowing on shadowing surfaces
    5696              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    5697              : 
    5698              :     // PURPOSE OF THIS SUBROUTINE:
    5699              :     // This subroutine is a driving routine for calculations of shadows
    5700              :     // and sunlit areas used in computing the solar beam flux multipliers.
    5701              : 
    5702              :     // REFERENCES:
    5703              :     // BLAST/IBLAST code, original author George Walton
    5704              : 
    5705              :     Real64 XS; // Intermediate result
    5706              :     Real64 YS; // Intermediate result
    5707              :     Real64 ZS; // Intermediate result
    5708              :     int N;     // Vertex number
    5709              :     int NGRS;  // Coordinate transformation index
    5710              :     int NVT;
    5711              :     int HTS;         // Heat transfer surface number of the general receiving surface
    5712              :     int GRSNR;       // Surface number of general receiving surface
    5713              :     int NBKS;        // Number of back surfaces
    5714              :     int NGSS;        // Number of general shadowing surfaces
    5715              :     int NSBS;        // Number of subsurfaces (windows and doors)
    5716              :     Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
    5717              :     // For windows, includes divider area
    5718              : 
    5719        33798 :     auto &s_surf = state.dataSurface;
    5720              : 
    5721        33798 :     if (state.dataSolarShading->ShadowOneTimeFlag) {
    5722          112 :         state.dataSolarShading->XVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
    5723          112 :         state.dataSolarShading->YVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
    5724          112 :         state.dataSolarShading->ZVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
    5725          112 :         state.dataSolarShading->XVrt = 0.0;
    5726          112 :         state.dataSolarShading->YVrt = 0.0;
    5727          112 :         state.dataSolarShading->ZVrt = 0.0;
    5728          112 :         state.dataSolarShading->ShadowOneTimeFlag = false;
    5729              :     }
    5730              : 
    5731              : #ifdef EP_Count_Calls
    5732              :     if (iHour == 0) {
    5733              :         ++state.dataTimingsData->NumShadow_Calls;
    5734              :     } else {
    5735              :         ++state.dataTimingsData->NumShadowAtTS_Calls;
    5736              :     }
    5737              : #endif
    5738              : 
    5739        33798 :     state.dataSolarShading->SurfSunlitArea = 0.0;
    5740              : 
    5741              : #ifndef EP_NO_OPENGL
    5742        33798 :     if (state.dataSolarShading->penumbra) {
    5743            0 :         Real64 ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
    5744            0 :         Real64 AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
    5745            0 :         state.dataSolarShading->penumbra->set_sun_position(AzimSun, ElevSun);
    5746            0 :         state.dataSolarShading->penumbra->submit_pssa();
    5747              :     }
    5748              : #endif
    5749              : 
    5750       301066 :     for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) {
    5751              : 
    5752       267268 :         if (!state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf) {
    5753       109386 :             continue;
    5754              :         }
    5755              : 
    5756       157882 :         state.dataSolarShading->SurfSunlitArea(GRSNR) = 0.0;
    5757              : 
    5758       157882 :         NGSS = state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf;
    5759       157882 :         state.dataSolarShading->NGSSHC = 0;
    5760       157882 :         NBKS = state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf;
    5761       157882 :         state.dataSolarShading->NBKSHC = 0;
    5762       157882 :         NSBS = state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf;
    5763       157882 :         state.dataSolarShading->NRVLHC = 0;
    5764       157882 :         state.dataSolarShading->NSBSHC = 0;
    5765       157882 :         state.dataSolarShading->LOCHCA = 1;
    5766              :         // Temporarily determine the old heat transfer surface number (HTS)
    5767       157882 :         HTS = GRSNR;
    5768              : 
    5769       157882 :         if (state.dataSolarShading->SurfSunCosTheta(GRSNR) < DataEnvironment::SunIsUpValue) { //.001) THEN ! Receiving surface is not in the sun
    5770              : 
    5771        74481 :             state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
    5772        74481 :             SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS);
    5773              : 
    5774        83401 :         } else if ((NGSS <= 0) && (NSBS <= 0)) { // Simple surface--no shaders or subsurfaces
    5775              : 
    5776        67614 :             state.dataSolarShading->SurfSunlitArea(HTS) = s_surf->Surface(GRSNR).NetAreaShadowCalc;
    5777              :         } else { // Surface in sun and either shading surfaces or subsurfaces present (or both)
    5778              : 
    5779              : #ifndef EP_NO_OPENGL
    5780        15787 :             int id = s_surf->SurfPenumbraID(HTS);
    5781        15787 :             if (state.dataSolarShading->penumbra && id >= 0) {
    5782              :                 // SurfSunlitArea(HTS) = buildingPSSF.at(id) / SurfSunCosTheta(HTS);
    5783            0 :                 state.dataSolarShading->SurfSunlitArea(HTS) =
    5784            0 :                     state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTS);
    5785              :                 // SurfSunlitArea(HTS) = penumbra->fetchPSSA(Surface(HTS).PenumbraID)/SurfSunCosTheta(HTS);
    5786            0 :                 for (int SS = 1; SS <= NSBS; ++SS) {
    5787            0 :                     int HTSS = state.dataShadowComb->ShadowComb(HTS).SubSurf(SS);
    5788            0 :                     id = s_surf->SurfPenumbraID(HTSS);
    5789            0 :                     if (id >= 0) {
    5790              :                         // SurfSunlitArea(HTSS) = buildingPSSF.at(id) / SurfSunCosTheta(HTSS);
    5791            0 :                         state.dataSolarShading->SurfSunlitArea(HTSS) =
    5792            0 :                             state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTSS);
    5793              :                         // SurfSunlitArea(HTSS) = penumbra->fetchPSSA(Surface(HTSS).PenumbraID)/SurfSunCosTheta(HTSS);
    5794            0 :                         if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
    5795            0 :                             if (iHour > 0 && TS > 0) {
    5796            0 :                                 state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
    5797            0 :                                     state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
    5798              :                             }
    5799              :                         }
    5800              :                     }
    5801              :                 }
    5802        15787 :             } else if (!state.dataSolarShading->penumbra) {
    5803              : #else
    5804              :             {
    5805              : #endif
    5806        15787 :                 NGRS = s_surf->Surface(GRSNR).BaseSurf;
    5807        15787 :                 if (s_surf->Surface(GRSNR).IsShadowing) {
    5808         7210 :                     NGRS = GRSNR;
    5809              :                 }
    5810              : 
    5811              :                 // Compute the X and Y displacements of a shadow.
    5812        15787 :                 XS = s_surf->Surface(NGRS).lcsx.x * state.dataSolarShading->SUNCOS(1) +
    5813        15787 :                      s_surf->Surface(NGRS).lcsx.y * state.dataSolarShading->SUNCOS(2) +
    5814        15787 :                      s_surf->Surface(NGRS).lcsx.z * state.dataSolarShading->SUNCOS(3);
    5815        15787 :                 YS = s_surf->Surface(NGRS).lcsy.x * state.dataSolarShading->SUNCOS(1) +
    5816        15787 :                      s_surf->Surface(NGRS).lcsy.y * state.dataSolarShading->SUNCOS(2) +
    5817        15787 :                      s_surf->Surface(NGRS).lcsy.z * state.dataSolarShading->SUNCOS(3);
    5818        15787 :                 ZS = s_surf->Surface(NGRS).lcsz.x * state.dataSolarShading->SUNCOS(1) +
    5819        15787 :                      s_surf->Surface(NGRS).lcsz.y * state.dataSolarShading->SUNCOS(2) +
    5820        15787 :                      s_surf->Surface(NGRS).lcsz.z * state.dataSolarShading->SUNCOS(3);
    5821              : 
    5822        15787 :                 if (std::abs(ZS) > Constant::SmallDistance) {
    5823        15787 :                     state.dataSolarShading->XShadowProjection = XS / ZS;
    5824        15787 :                     state.dataSolarShading->YShadowProjection = YS / ZS;
    5825        15787 :                     if (std::abs(state.dataSolarShading->XShadowProjection) < 1.e-8) {
    5826          900 :                         state.dataSolarShading->XShadowProjection = 0.0;
    5827              :                     }
    5828        15787 :                     if (std::abs(state.dataSolarShading->YShadowProjection) < 1.e-8) {
    5829          384 :                         state.dataSolarShading->YShadowProjection = 0.0;
    5830              :                     }
    5831              :                 } else {
    5832            0 :                     state.dataSolarShading->XShadowProjection = 0.0;
    5833            0 :                     state.dataSolarShading->YShadowProjection = 0.0;
    5834              :                 }
    5835              : 
    5836        15787 :                 CTRANS(state,
    5837              :                        GRSNR,
    5838              :                        NGRS,
    5839              :                        NVT,
    5840        15787 :                        state.dataSolarShading->XVrt,
    5841        15787 :                        state.dataSolarShading->YVrt,
    5842        15787 :                        state.dataSolarShading->ZVrt); // Transform coordinates of the receiving surface to 2-D form
    5843              : 
    5844              :                 // Re-order its vertices to clockwise sequential.
    5845        78935 :                 for (N = 1; N <= NVT; ++N) {
    5846        63148 :                     state.dataSolarShading->XVS(N) = state.dataSolarShading->XVrt(NVT + 1 - N);
    5847        63148 :                     state.dataSolarShading->YVS(N) = state.dataSolarShading->YVrt(NVT + 1 - N);
    5848              :                 }
    5849              : 
    5850        15787 :                 HTRANS1(state, 1, NVT); // Transform to homogeneous coordinates.
    5851              : 
    5852        15787 :                 state.dataSolarShading->HCAREA(1) = -state.dataSolarShading->HCAREA(1); // Compute (+) gross surface area.
    5853        15787 :                 state.dataSolarShading->HCT(1) = 1.0;
    5854              : 
    5855        15787 :                 SHDGSS(state, NGRS, iHour, TS, GRSNR, NGSS, HTS); // Determine shadowing on surface.
    5856              : 
    5857        15787 :                 if (!state.dataSolarShading->CalcSkyDifShading) {
    5858         9865 :                     SHDBKS(state, s_surf->Surface(GRSNR).BaseSurf, GRSNR, NBKS, HTS); // Determine possible back surfaces.
    5859              :                 }
    5860              :             }
    5861              : 
    5862        15787 :             SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS); // Subtract subsurf areas from total
    5863              : 
    5864              :             // Error checking:  require that 0 <= SurfSunlitArea <= AREA.  + or - .01*AREA added for round-off errors
    5865        15787 :             SurfArea = s_surf->Surface(GRSNR).NetAreaShadowCalc;
    5866        15787 :             state.dataSolarShading->SurfSunlitArea(HTS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTS));
    5867              : 
    5868        15787 :             state.dataSolarShading->SurfSunlitArea(HTS) = min(state.dataSolarShading->SurfSunlitArea(HTS), SurfArea);
    5869              :         } // ...end of surface in sun/surface with shaders and/or subsurfaces IF-THEN block
    5870              : 
    5871              :         // NOTE:
    5872              :         // There used to be a call to legacy subroutine SHDCVR here when the
    5873              :         // zone type was not a standard zone.
    5874              :     }
    5875        33798 : }
    5876              : 
    5877         9865 : void SHDBKS(EnergyPlusData &state,
    5878              :             int const NGRS, // Number of the general receiving surface
    5879              :             int const CurSurf,
    5880              :             int const NBKS, // Number of back surfaces
    5881              :             int const HTS   // Heat transfer surface number of the general receiving surf
    5882              : )
    5883              : {
    5884              : 
    5885              :     // SUBROUTINE INFORMATION:
    5886              :     //       AUTHOR         Legacy Code
    5887              :     //       DATE WRITTEN
    5888              :     //       MODIFIED       na
    5889              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    5890              : 
    5891              :     // PURPOSE OF THIS SUBROUTINE:
    5892              :     // This is the driving subroutine for computing
    5893              :     // the sunlit areas for back surfaces.
    5894              : 
    5895              :     // REFERENCES:
    5896              :     // BLAST/IBLAST code, original author George Walton
    5897              : 
    5898              :     typedef Array2D<Int64>::size_type size_type;
    5899              :     int I;
    5900              :     int M;
    5901              :     int N;
    5902              :     int NVR;
    5903              :     int NVT; // Number of vertices of back surface
    5904              :     int BackSurfaceNumber;
    5905              :     int NS1; // Number of the figure being overlapped
    5906              :     int NS2; // Number of the figure doing overlapping
    5907              :     int NS3; // Location to place results of overlap
    5908              : 
    5909         9865 :     auto &s_surf = state.dataSurface;
    5910              : 
    5911              :     // Tuned Linear indexing
    5912              : 
    5913         9865 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    5914         9865 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    5915              : 
    5916         9865 :     if (state.dataSolarShading->SHDBKSOneTimeFlag) {
    5917           27 :         state.dataSolarShading->XVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
    5918           27 :         state.dataSolarShading->YVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
    5919           27 :         state.dataSolarShading->ZVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
    5920           27 :         state.dataSolarShading->XVrtx = 0.0;
    5921           27 :         state.dataSolarShading->YVrtx = 0.0;
    5922           27 :         state.dataSolarShading->ZVrtx = 0.0;
    5923           27 :         state.dataSolarShading->SHDBKSOneTimeFlag = false;
    5924              :     }
    5925              : 
    5926        10570 :     if ((NBKS <= 0) || (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) || (state.dataSolarShading->OverlapStatus == TooManyVertices) ||
    5927          705 :         (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    5928         9160 :         return;
    5929              :     }
    5930              : 
    5931          705 :     state.dataSolarShading->FBKSHC = state.dataSolarShading->LOCHCA + 1;
    5932              : 
    5933         4230 :     for (I = 1; I <= NBKS; ++I) { // Loop through all back surfaces associated with the receiving surface
    5934              : 
    5935         3525 :         BackSurfaceNumber = state.dataShadowComb->ShadowComb(CurSurf).BackSurf(I);
    5936              : 
    5937         3525 :         if (state.dataSolarShading->SurfSunCosTheta(BackSurfaceNumber) > -DataEnvironment::SunIsUpValue) {
    5938         1410 :             continue; //-0.001) CYCLE ! go to next back surface since inside of this surface
    5939              :         }
    5940              :         // cannot be in sun if the outside can be
    5941              : 
    5942              :         // Transform coordinates of back surface from general system to the
    5943              :         // plane of the receiving surface
    5944              : 
    5945         2115 :         CTRANS(state, BackSurfaceNumber, NGRS, NVT, state.dataSolarShading->XVrtx, state.dataSolarShading->YVrtx, state.dataSolarShading->ZVrtx);
    5946              : 
    5947              :         // Project "shadow" from back surface along sun's rays to receiving surface.  Back surface vertices
    5948              :         // become clockwise sequential.
    5949              : 
    5950        10575 :         for (N = 1; N <= NVT; ++N) {
    5951         8460 :             state.dataSolarShading->XVS(N) =
    5952         8460 :                 state.dataSolarShading->XVrtx(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVrtx(N);
    5953         8460 :             state.dataSolarShading->YVS(N) =
    5954         8460 :                 state.dataSolarShading->YVrtx(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVrtx(N);
    5955              :         }
    5956              : 
    5957              :         // Transform to the homogeneous coordinate system.
    5958              : 
    5959         2115 :         NS3 = state.dataSolarShading->LOCHCA + 1;
    5960         2115 :         state.dataSolarShading->HCT(NS3) = 0.0;
    5961         2115 :         HTRANS1(state, NS3, NVT);
    5962              : 
    5963              :         // Adjust near-duplicate points.
    5964              : 
    5965         2115 :         NVR = state.dataSolarShading->HCNV(1);
    5966         2115 :         int l3 = state.dataSolarShading->HCX.index(NS3, 1);
    5967        10575 :         for (N = 1; N <= NVT; ++N, ++l3) {
    5968         8460 :             Real64 const x3 = state.dataSolarShading->HCX[l3]; // [ l3 ] == ( NS3, N )
    5969         8460 :             Real64 const y3 = state.dataSolarShading->HCY[l3];
    5970         8460 :             size_type l1 = 0;
    5971        35240 :             for (M = 1; M <= NVR; ++M, ++l1) {
    5972        29600 :                 if (std::abs(state.dataSolarShading->HCX[l1] - x3) > 6) {
    5973        25370 :                     continue; // [ l1 ] == ( 1, M )
    5974              :                 }
    5975         4230 :                 if (std::abs(state.dataSolarShading->HCY[l1] - y3) > 6) {
    5976         1410 :                     continue;
    5977              :                 }
    5978         2820 :                 state.dataSolarShading->HCX[l3] = state.dataSolarShading->HCX[l1];
    5979         2820 :                 state.dataSolarShading->HCY[l3] = state.dataSolarShading->HCY[l1];
    5980         2820 :                 break;
    5981              :             }
    5982              :         }
    5983              : 
    5984         2115 :         HTRANS0(state, NS3, NVT);
    5985              : 
    5986              :         // Determine area of overlap of projected back surface and receiving surface.
    5987              : 
    5988         2115 :         NS1 = 1;
    5989         2115 :         NS2 = NS3;
    5990         2115 :         state.dataSolarShading->HCT(NS3) = 1.0;
    5991         2115 :         DeterminePolygonOverlap(state, NS1, NS2, NS3);
    5992              : 
    5993         2115 :         if (state.dataSolarShading->OverlapStatus == NoOverlap) {
    5994          669 :             continue; // to next back surface
    5995              :         }
    5996         1446 :         if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    5997            0 :             break; // back surfaces DO loop
    5998              :         }
    5999              : 
    6000              :         // Increment back surface count.
    6001              : 
    6002         1446 :         state.dataSolarShading->LOCHCA = NS3;
    6003         1446 :         state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
    6004         1446 :         state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
    6005         1446 :         state.dataSolarShading->NBKSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FBKSHC + 1;
    6006              :     }
    6007              : }
    6008              : 
    6009        15787 : void SHDGSS(EnergyPlusData &state,
    6010              :             int const NGRS,
    6011              :             int const iHour,   // Hour Counter
    6012              :             int const TS,      // TimeStep
    6013              :             int const CurSurf, // Current Surface
    6014              :             int const NGSS,    // Number of general shadowing surfaces
    6015              :             int const HTS      // Heat transfer surface number of the general receiving surf
    6016              : )
    6017              : {
    6018              : 
    6019              :     // SUBROUTINE INFORMATION:
    6020              :     //       AUTHOR         Legacy Code
    6021              :     //       DATE WRITTEN
    6022              :     //       MODIFIED       na
    6023              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    6024              : 
    6025              :     // PURPOSE OF THIS SUBROUTINE:
    6026              :     // This subroutine determines the shadows on a general receiving surface.
    6027              : 
    6028              :     // REFERENCES:
    6029              :     // BLAST/IBLAST code, original author George Walton
    6030              : 
    6031              :     typedef Array2D<Int64>::size_type size_type;
    6032              :     int GSSNR;             // General shadowing surface number
    6033              :     int MainOverlapStatus; // Overlap status of the main overlap calculation not the check for
    6034              :     // multiple overlaps (unless there was an error)
    6035              :     int NS1;         // Number of the figure being overlapped
    6036              :     int NS2;         // Number of the figure doing overlapping
    6037              :     int NS3;         // Location to place results of overlap
    6038              :     Real64 SchValue; // Value for Schedule of shading transmittance
    6039              : 
    6040        15787 :     auto &s_surf = state.dataSurface;
    6041              : 
    6042        15787 :     if (state.dataSolarShading->SHDGSSOneTimeFlag) {
    6043           29 :         state.dataSolarShading->XVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
    6044           29 :         state.dataSolarShading->YVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
    6045           29 :         state.dataSolarShading->ZVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
    6046           29 :         state.dataSolarShading->SHDGSSOneTimeFlag = false;
    6047              :     }
    6048              : 
    6049        15787 :     state.dataSolarShading->FGSSHC = state.dataSolarShading->LOCHCA + 1;
    6050        15787 :     MainOverlapStatus = NoOverlap; // Set to ensure that the value from the last surface is not saved
    6051        15787 :     state.dataSolarShading->OverlapStatus = NoOverlap;
    6052              : 
    6053        15787 :     if (NGSS <= 0) { // IF NO S.S., receiving surface FULLY SUNLIT.
    6054              : 
    6055         4958 :         state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
    6056              : 
    6057              :     } else {
    6058              : 
    6059        10829 :         int ExitLoopStatus = -1;
    6060        10829 :         auto const &GenSurf = state.dataShadowComb->ShadowComb(CurSurf).GenSurf;
    6061        10829 :         int const sunIsUp = DataEnvironment::SunIsUpValue;
    6062        27796 :         for (int I = 1; I <= NGSS; ++I) { // Loop through all shadowing surfaces...
    6063              : 
    6064        17924 :             GSSNR = GenSurf(I);
    6065              : 
    6066        17924 :             if (state.dataSolarShading->SurfSunCosTheta(GSSNR) > sunIsUp) {
    6067         5001 :                 continue; //.001) CYCLE ! NO SHADOW IF GSS IN SUNLIGHT.
    6068              :             }
    6069              : 
    6070        12923 :             auto const &surface = s_surf->Surface(GSSNR);
    6071        12923 :             bool const notHeatTransSurf = !surface.HeatTransSurf;
    6072              : 
    6073              :             //     This used to check to see if the shadowing surface was not opaque (within the scheduled dates of
    6074              :             //            transmittance value.  Perhaps it ignored it if it were outside the range.  (if so, was an error)
    6075              :             //     The proper action seems to be delete this statement all together, but there would also be no shading if
    6076              :             //            the shading surface were transparent...
    6077              :             //---former stmt      IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
    6078              :             //---former stmt            GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex,IHOUR) == 0.0) CYCLE
    6079              : 
    6080        12923 :             if (notHeatTransSurf) {
    6081         8315 :                 if (surface.IsTransparent) {
    6082            0 :                     continue; // No shadow if shading surface is transparent
    6083              :                 }
    6084         8315 :                 if (surface.shadowSurfSched != nullptr) {
    6085         6819 :                     if (surface.shadowSurfSched->getHrTsVal(state, iHour) == 1.0) {
    6086         1097 :                         continue;
    6087              :                     }
    6088         5722 :                     if (!state.dataSolarShading->CalcSkyDifShading) {
    6089         3619 :                         if (surface.shadowSurfSched->getHrTsVal(state, iHour, TS) == 1.0) {
    6090            0 :                             continue;
    6091              :                         }
    6092              :                     }
    6093              :                 }
    6094              :             }
    6095              :             // Eliminate shadowing surfaces that is supposed to be disabled.
    6096        11826 :             if (state.dataSysVars->DisableAllSelfShading) {
    6097            0 :                 if (surface.Zone != 0) {
    6098            0 :                     continue; // Disable all shadowing surfaces in all zones. Attached shading surfaces are not part of a zone, zone value is 0.
    6099              :                 }
    6100        11826 :             } else if (state.dataSysVars->DisableGroupSelfShading) {
    6101            0 :                 std::vector<int> DisabledZones = s_surf->SurfShadowDisabledZoneList(CurSurf);
    6102            0 :                 bool isDisabledShadowSurf = false;
    6103            0 :                 for (int i : DisabledZones) {
    6104            0 :                     if (surface.Zone == i) {
    6105            0 :                         isDisabledShadowSurf = true;
    6106            0 :                         break;
    6107              :                     }
    6108            0 :                 }
    6109            0 :                 if (isDisabledShadowSurf) {
    6110            0 :                     continue; // Disable all shadowing surfaces in all disabled zones.
    6111              :                 }
    6112            0 :             }
    6113              : 
    6114              :             //      IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
    6115              :             //            GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex) == 1.0) CYCLE
    6116              : 
    6117              :             // Transform shadow casting surface from cartesian to homogeneous coordinates according to surface type.
    6118              : 
    6119        11826 :             if ((notHeatTransSurf) && (surface.BaseSurf != 0)) {
    6120              : 
    6121              :                 // For shadowing subsurface coordinates of shadow casting surface are relative to the receiving surface
    6122              :                 // project shadow to the receiving surface
    6123              : 
    6124            0 :                 state.dataSolarShading->NVS = surface.Sides;
    6125            0 :                 auto const &XV = s_surf->ShadeV(GSSNR).XV;
    6126            0 :                 auto const &YV = s_surf->ShadeV(GSSNR).YV;
    6127            0 :                 auto const &ZV = s_surf->ShadeV(GSSNR).ZV;
    6128            0 :                 for (int N = 1; N <= state.dataSolarShading->NVS; ++N) {
    6129            0 :                     state.dataSolarShading->XVS(N) = XV(N) - state.dataSolarShading->XShadowProjection * ZV(N);
    6130            0 :                     state.dataSolarShading->YVS(N) = YV(N) - state.dataSolarShading->YShadowProjection * ZV(N);
    6131              :                 }
    6132              : 
    6133            0 :             } else {
    6134              :                 // Transform coordinates of shadow casting surface from general system to the system relative to the receiving surface
    6135              :                 int NVT;
    6136        11826 :                 CTRANS(state, GSSNR, NGRS, NVT, state.dataSolarShading->XVert, state.dataSolarShading->YVert, state.dataSolarShading->ZVert);
    6137        11826 :                 CLIP(state,
    6138              :                      NVT,
    6139        11826 :                      state.dataSolarShading->XVert,
    6140        11826 :                      state.dataSolarShading->YVert,
    6141        11826 :                      state.dataSolarShading->ZVert); // Clip portions of the shadow casting surface which are behind the receiving surface
    6142              : 
    6143        11826 :                 if (state.dataSolarShading->NumVertInShadowOrClippedSurface <= 2) {
    6144            0 :                     continue;
    6145              :                 }
    6146              : 
    6147              :                 // Project shadow from shadow casting surface along sun's rays to receiving surface Shadow vertices
    6148              :                 // become clockwise sequential
    6149              : 
    6150        59098 :                 for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface; ++N) {
    6151        47272 :                     state.dataSolarShading->XVS(N) =
    6152        47272 :                         state.dataSolarShading->XVC(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVC(N);
    6153        47272 :                     state.dataSolarShading->YVS(N) =
    6154        47272 :                         state.dataSolarShading->YVC(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVC(N);
    6155              :                 }
    6156              :             }
    6157              : 
    6158              :             // Transform to the homogeneous coordinate system.
    6159              : 
    6160        11826 :             NS3 = state.dataSolarShading->LOCHCA + 1;
    6161        11826 :             HTRANS1(state, NS3, state.dataSolarShading->NVS);
    6162              : 
    6163              :             // Adjust near-duplicate points.
    6164              : 
    6165        11826 :             assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    6166        11826 :             assert(state.dataSolarShading->HCX.index(1, 1) == 0u);
    6167        11826 :             size_type j(state.dataSolarShading->HCX.index(NS3, 1));
    6168        11826 :             size_type NVR(state.dataSolarShading->HCNV(1));
    6169        59098 :             for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface;
    6170        47272 :                  ++N, ++j) {                                       // Tuned Logic change: break after 1st "close" point found
    6171        47272 :                 Int64 const HCX_N(state.dataSolarShading->HCX[j]); // [ j ] == ( NS3, N )
    6172        47272 :                 Int64 const HCY_N(state.dataSolarShading->HCY[j]);
    6173       234767 :                 for (size_type l = 0; l < NVR; ++l) { // [ l ] == ( 1, l+1 )
    6174       188150 :                     Real64 const delX = std::abs(state.dataSolarShading->HCX[l] - HCX_N);
    6175       188150 :                     if (delX > 6) {
    6176       184714 :                         continue;
    6177              :                     }
    6178         3436 :                     Real64 const delY = std::abs(state.dataSolarShading->HCY[l] - HCY_N);
    6179         3436 :                     if (delY > 6) {
    6180         2781 :                         continue;
    6181              :                     }
    6182          655 :                     if (delX > 0) {
    6183            0 :                         state.dataSolarShading->HCX[j] = state.dataSolarShading->HCX[l]; // [ j ] == ( NS3, N )
    6184              :                     }
    6185          655 :                     if (delY > 0) {
    6186            0 :                         state.dataSolarShading->HCY[j] = state.dataSolarShading->HCY[l];
    6187              :                     }
    6188          655 :                     break;
    6189              :                 }
    6190              :             }
    6191        11826 :             HTRANS0(state, NS3, state.dataSolarShading->NumVertInShadowOrClippedSurface);
    6192        11826 :             if (!state.dataSolarShading->CalcSkyDifShading && surface.shadowSurfSched != nullptr) {
    6193         3619 :                 if (iHour != 0) {
    6194         3619 :                     SchValue = surface.shadowSurfSched->getHrTsVal(state, iHour, TS);
    6195              :                 } else {
    6196            0 :                     SchValue = surface.SchedMinValue;
    6197              :                 }
    6198              :             } else {
    6199         8207 :                 SchValue = surface.SchedMinValue;
    6200              :             }
    6201              : 
    6202        11826 :             state.dataSolarShading->HCT(NS3) = SchValue;
    6203              : 
    6204              :             // Determine overlap of shadow with receiving surface
    6205              : 
    6206        11826 :             state.dataSolarShading->CurrentShadowingSurface = I;
    6207        11826 :             state.dataSolarShading->CurrentSurfaceBeingShadowed = GSSNR;
    6208        11826 :             NS1 = 1;
    6209        11826 :             NS2 = NS3;
    6210        11826 :             DeterminePolygonOverlap(state, NS1, NS2, NS3);
    6211              :             //  Next statement is special to deal with transmitting shading devices
    6212        11826 :             if (state.dataSolarShading->OverlapStatus == FirstSurfWithinSecond && SchValue > 0.0) {
    6213           67 :                 state.dataSolarShading->OverlapStatus = PartialOverlap;
    6214              :             }
    6215        11826 :             MainOverlapStatus = state.dataSolarShading->OverlapStatus;
    6216        11826 :             ExitLoopStatus = MainOverlapStatus;
    6217              : 
    6218        11826 :             if (MainOverlapStatus == NoOverlap) { // No overlap of general surface shadow and receiving surface
    6219              :                                                   // Continue
    6220         7693 :             } else if ((MainOverlapStatus == FirstSurfWithinSecond) || (MainOverlapStatus == TooManyVertices) ||
    6221              :                        (MainOverlapStatus == TooManyFigures)) {
    6222          957 :                 goto ShadowingSurfaces_exit;
    6223         6736 :             } else if ((MainOverlapStatus == SecondSurfWithinFirst) || (MainOverlapStatus == PartialOverlap)) {
    6224              :                 // Determine overlaps with previous shadows.
    6225         6736 :                 state.dataSolarShading->LOCHCA = NS3;
    6226         6736 :                 state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
    6227         7863 :                 if (state.dataSolarShading->NGSSHC > 1) {
    6228         1127 :                     MULTOL(state,
    6229         1127 :                            state.dataSolarShading->LOCHCA,
    6230         1127 :                            state.dataSolarShading->FGSSHC - 1,
    6231         1127 :                            state.dataSolarShading->NGSSHC - 1); // HOYT - Remove this call
    6232              :                 }
    6233              :             } else {
    6234            0 :                 goto ShadowingSurfaces_exit;
    6235              :             }
    6236              : 
    6237        10869 :             ExitLoopStatus = -1;
    6238              :         }
    6239         9872 :     ShadowingSurfaces_exit:;
    6240              : 
    6241              :         // Compute sunlit area of surface (excluding effects of subsurfs).
    6242              : 
    6243        10829 :         if (ExitLoopStatus == FirstSurfWithinSecond) { // Surface fully shaded
    6244          957 :             state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
    6245          957 :             state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
    6246              : 
    6247         9872 :         } else if ((ExitLoopStatus == TooManyVertices) || (ExitLoopStatus == TooManyFigures)) { // Array limits exceeded, estimate
    6248            0 :             state.dataSolarShading->SurfSunlitArea(HTS) = 0.25 * state.dataSolarShading->HCAREA(1);
    6249              : 
    6250              :         } else {
    6251              : 
    6252              :             // Compute the sunlit area here.
    6253              :             // Call UnionShadow(FGSSHC,LOCHCA)
    6254              : 
    6255         9872 :             state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
    6256         9872 :             if (state.dataSolarShading->NGSSHC <= 0) {
    6257         4263 :                 state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
    6258              :             } else {
    6259         5609 :                 Real64 A(state.dataSolarShading->HCAREA(1)); // Area
    6260        12935 :                 for (int i = state.dataSolarShading->FGSSHC, e = state.dataSolarShading->FGSSHC + state.dataSolarShading->NGSSHC - 1; i <= e; ++i) {
    6261         7326 :                     A += state.dataSolarShading->HCAREA(i) * (1.0 - state.dataSolarShading->HCT(i));
    6262              :                 }
    6263         5609 :                 state.dataSolarShading->SurfSunlitArea(HTS) = A;
    6264         5609 :                 if (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) { // Surface fully shaded
    6265           25 :                     state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
    6266           25 :                     state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
    6267              :                 }
    6268              :             }
    6269              :         }
    6270              :     }
    6271        15787 :     state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
    6272        15787 : }
    6273              : 
    6274         6982 : void CalcInteriorSolarOverlaps(EnergyPlusData &state,
    6275              :                                int const iHour, // Hour Index
    6276              :                                int const NBKS,  // Number of back surfaces associated with this GRSNR (in general, only
    6277              :                                int const HTSS,  // Surface number of the subsurface (exterior window)
    6278              :                                int const GRSNR, // General receiving surface number (base surface of the exterior window)
    6279              :                                int const TS     // Time step Index
    6280              : )
    6281              : {
    6282              : 
    6283              :     // SUBROUTINE INFORMATION:
    6284              :     //       AUTHOR         Fred Winkelmann
    6285              :     //       DATE WRITTEN   January 1999
    6286              :     //       MODIFIED       Nov 2001, FW: include beam radiation overlaps with
    6287              :     //                       back windows and doors; previously these subsurfaces ignored.
    6288              :     //                      May 2002, FW: fix problem where reveal was not being considered
    6289              :     //                       in calculating overlap areas if window is shaded only by reveal.
    6290              :     //                      June 2002, FW: fix problem that gave incorrect calculation when
    6291              :     //                       window is not shaded only by reveal
    6292              :     //                      June 2002, FW: remove incorrect multiplication of overlap areas
    6293              :     //                       by sunlit fraction when window is shaded only by reveal
    6294              : 
    6295              :     // PURPOSE OF THIS SUBROUTINE:
    6296              :     // For an exterior window with surface number HTSS, determines (1) the surface numbers of back
    6297              :     // surfaces receiving beam radiation from the window and (2) for each such back surface, the area
    6298              :     // of the portion of the window sending beam radiation to the back surface; this is called the
    6299              :     // "overlap area."
    6300              : 
    6301              :     // REFERENCES:
    6302              :     // BLAST/IBLAST code, original author George Walton
    6303              : 
    6304              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    6305              :     //  some of these will receive beam radiation from HTSS this hour)
    6306              : 
    6307              :     // SUBROUTINE PARAMETER DEFINITIONS:
    6308         6982 :     int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
    6309              : 
    6310              :     typedef Array2D<Int64>::size_type size_type;
    6311              :     int JBKS;        // Counter of back surfaces with non-zero overlap with HTSS
    6312              :     int BackSurfNum; // Back surface number
    6313              : 
    6314              :     bool UseSimpleDistribution; // TRUE means simple interior solar distribution
    6315              :     // (all incoming beam assumed to strike floor),
    6316              :     // FALSE means exact interior solar distribution
    6317              :     // (track which back surfaces beam illuminates)
    6318              : 
    6319         6982 :     auto &s_surf = state.dataSurface;
    6320              : 
    6321              :     // Tuned Linear indexing
    6322              : 
    6323         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    6324         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    6325         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    6326         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    6327              : 
    6328         6982 :     if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
    6329              : 
    6330         3822 :         UseSimpleDistribution = false;
    6331              : 
    6332         3822 :         if ((NBKS <= 0) || (s_surf->Surface(GRSNR).ExtBoundCond > 0)) {
    6333              : 
    6334         3117 :             UseSimpleDistribution = true;
    6335              : 
    6336              :         } else {
    6337              :             // Using 'exact' distribution, replace subsurface HC entries with reveal HC entries
    6338              :             // so that the reveal HC is used in calculating interior solar overlap areas
    6339              : 
    6340              :             // Adding the following line fixes a problem where, if the window was shaded only
    6341              :             // by reveal, then the reveal was not considered in calculating interior solar
    6342              :             // overlap areas (FCW 5/3/02).
    6343              :             // IF(Surface(HTSS)%Reveal > 0.0) NRVLHC = 1
    6344              :             // Changing the line to the following avoids incorrect calculation when window is not shaded
    6345              :             // only by reveal (FCW 6/28/02).
    6346          705 :             if (state.dataSolarShading->SurfWinRevealStatus(iHour, TS, HTSS) == WindowShadedOnlyByReveal) {
    6347            0 :                 state.dataSolarShading->NRVLHC = 1;
    6348              :             }
    6349          705 :             if (state.dataSolarShading->NRVLHC > 0) {
    6350            0 :                 for (int I = 1; I <= state.dataSolarShading->NRVLHC; ++I) {
    6351            0 :                     int const iS(state.dataSolarShading->FSBSHC - 1 + I);
    6352            0 :                     int const iR(state.dataSolarShading->FRVLHC - 1 + I);
    6353            0 :                     state.dataSolarShading->HCT(iS) = state.dataSolarShading->HCT(iR);
    6354            0 :                     state.dataSolarShading->HCNV(iS) = state.dataSolarShading->HCNV(iR);
    6355            0 :                     state.dataSolarShading->HCAREA(iS) = state.dataSolarShading->HCAREA(iR);
    6356            0 :                     size_type lS(state.dataSolarShading->HCX.index(iS, 1));
    6357            0 :                     size_type lR(state.dataSolarShading->HCX.index(iR, 1));
    6358            0 :                     for (int J = 1; J <= state.dataSolarShading->MaxHCV; ++J, ++lS, ++lR) { // [ lS ] == ( iS, J ), [ lR ] == ( iR, J )
    6359            0 :                         state.dataSolarShading->HCX[lS] = state.dataSolarShading->HCX[lR];
    6360            0 :                         state.dataSolarShading->HCY[lS] = state.dataSolarShading->HCY[lR];
    6361            0 :                         state.dataSolarShading->HCA[lS] = state.dataSolarShading->HCA[lR];
    6362            0 :                         state.dataSolarShading->HCB[lS] = state.dataSolarShading->HCB[lR];
    6363            0 :                         state.dataSolarShading->HCC[lS] = state.dataSolarShading->HCC[lR];
    6364              :                     }
    6365              :                 }
    6366            0 :                 state.dataSolarShading->NSBSHC = state.dataSolarShading->NRVLHC;
    6367              :             }
    6368              :         }
    6369              : 
    6370              :         // Check for array space.
    6371         3822 :         if (state.dataSolarShading->FSBSHC + state.dataSolarShading->NBKSHC > state.dataSolarShading->MaxHCS) {
    6372            0 :             UseSimpleDistribution = true;
    6373              :         }
    6374              : 
    6375         3822 :         if (!UseSimpleDistribution) { // Compute overlaps
    6376              : 
    6377          705 :             std::unordered_map<unsigned, float> pssas;
    6378              : 
    6379              : #ifndef EP_NO_OPENGL
    6380          705 :             if (state.dataSolarShading->penumbra) {
    6381              :                 // Add back surfaces to array
    6382            0 :                 std::vector<unsigned> pbBackSurfaces;
    6383            0 :                 for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
    6384            0 :                     if (bkSurfNum == 0) {
    6385            0 :                         continue;
    6386              :                     }
    6387            0 :                     if (state.dataSolarShading->SurfSunCosTheta(bkSurfNum) < DataEnvironment::SunIsUpValue) {
    6388            0 :                         pbBackSurfaces.push_back(s_surf->SurfPenumbraID(bkSurfNum));
    6389              :                     }
    6390              :                 }
    6391            0 :                 pssas = state.dataSolarShading->penumbra->calculate_interior_pssas({(unsigned)s_surf->SurfPenumbraID(HTSS)}, pbBackSurfaces);
    6392              :                 // penumbra->render_interior_scene({(unsigned)Surface(HTSS).PenumbraID}, pbBackSurfaces);
    6393              : 
    6394            0 :                 JBKS = 0;
    6395            0 :                 for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
    6396            0 :                     if (bkSurfNum == 0) {
    6397            0 :                         continue;
    6398              :                     }
    6399            0 :                     if (pssas[s_surf->SurfPenumbraID(bkSurfNum)] > 0) {
    6400            0 :                         ++JBKS;
    6401            0 :                         state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = bkSurfNum;
    6402            0 :                         Real64 OverlapArea = pssas[s_surf->SurfPenumbraID(bkSurfNum)] / state.dataSolarShading->SurfSunCosTheta(HTSS);
    6403            0 :                         state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
    6404              :                     }
    6405              :                 }
    6406            0 :             }
    6407              : #endif
    6408              : 
    6409          705 :             if (!state.dataSolarShading->penumbra) {
    6410              : 
    6411          705 :                 state.dataSolarShading->FINSHC = state.dataSolarShading->FSBSHC + state.dataSolarShading->NSBSHC;
    6412              : 
    6413          705 :                 JBKS = 0;
    6414              : 
    6415         2151 :                 for (int IBKS = 1; IBKS <= state.dataSolarShading->NBKSHC;
    6416              :                      ++IBKS) { // Loop over back surfaces to GRSNR this hour. NBKSHC is the number of
    6417              :                     // back surfaces that would receive beam radiation from the base surface, GRSNR,
    6418              :                     // if the base surface was transparent. In general, some (at least one) or all of these
    6419              :                     // will receive beam radiation from the exterior window subsurface, HTSS, of GRSNR,
    6420              :                     // depending on the size of HTSS and its location on GRSNR
    6421              : 
    6422         1446 :                     BackSurfNum = state.dataSolarShading->HCNS(state.dataSolarShading->FBKSHC - 1 + IBKS);
    6423              : 
    6424              :                     // Determine if this back surface number can receive beam radiation from the
    6425              :                     // exterior window, HTSS, this hour, i.e., overlap area is positive
    6426              : 
    6427         1446 :                     state.dataSolarShading->LOCHCA = state.dataSolarShading->FINSHC - 1;
    6428              : 
    6429         1446 :                     MULTOL(state, state.dataSolarShading->FBKSHC - 1 + IBKS, state.dataSolarShading->FSBSHC - 1, state.dataSolarShading->NSBSHC);
    6430              : 
    6431              :                     // Compute overlap area for this back surface
    6432              : 
    6433         1446 :                     state.dataSolarShading->NINSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FINSHC + 1;
    6434         1446 :                     if (state.dataSolarShading->NINSHC <= 0) {
    6435          224 :                         continue;
    6436              :                     }
    6437         1222 :                     Real64 OverlapArea = state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC);
    6438         1222 :                     for (int J = 2; J <= state.dataSolarShading->NINSHC; ++J) {
    6439            0 :                         OverlapArea += state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC - 1 + J) *
    6440            0 :                                        (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FINSHC - 1 + J));
    6441              :                     }
    6442              : 
    6443         1222 :                     if (OverlapArea > 0.001) {
    6444         1222 :                         ++JBKS;
    6445         1222 :                         if (JBKS <= state.dataBSDFWindow->MaxBkSurf) {
    6446         1222 :                             state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = BackSurfNum;
    6447         1222 :                             int baseSurfaceNum = s_surf->Surface(BackSurfNum).BaseSurf;
    6448         1222 :                             state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
    6449              :                             // If this is a subsurface, subtract its overlap area from its base surface
    6450         1222 :                             if (baseSurfaceNum != BackSurfNum) {
    6451            0 :                                 for (int iBaseBKS = 1; iBaseBKS <= JBKS; ++iBaseBKS) {
    6452            0 :                                     if (baseSurfaceNum == state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, iBaseBKS, HTSS)) {
    6453            0 :                                         state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) =
    6454            0 :                                             max(0.0,
    6455            0 :                                                 state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) -
    6456            0 :                                                     state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS));
    6457            0 :                                         break;
    6458              :                                     }
    6459              :                                 }
    6460              :                             }
    6461              :                         }
    6462              :                     }
    6463              :                 } // End of loop over back surfaces
    6464              :             }
    6465          705 :         }
    6466              :     } // End of check that sunlit area > 0.
    6467         6982 : }
    6468              : 
    6469        71220 : void CalcInteriorSolarDistribution(EnergyPlusData &state)
    6470              : {
    6471              : 
    6472              :     // SUBROUTINE INFORMATION:
    6473              :     //       AUTHOR         Fred Winkelmann
    6474              :     //       DATE WRITTEN   January 1999
    6475              :     //       MODIFIED       Nov 1999, FW, for Window5 calculation method
    6476              :     //                      Oct 2000, FW: add transmitted solar variables for reporting
    6477              :     //                      Mar 2001, FW: add new calc of solar absorbed by window shades
    6478              :     //                      May 2001, FW: add calc of solar transmitted and absorbed by window blinds
    6479              :     //                      Oct 2001, LL: remove interpolation, solar now at time step
    6480              :     //                      Oct 2001, FW: add solar transmitted through interior windows
    6481              :     //                      Mar 24, 2001, FW: remove incorrect multiplication of Boverlap by sunlit fraction
    6482              :     //                                        since effect of shadowing is already included in Aoverlap
    6483              :     //                      Apr 2001, FW: add effects of beam solar reflection from outside and inside reveals
    6484              :     //                      Jan 2003, FW: add between-glass shades and blinds
    6485              :     //                      Dec 2003, FW: report beam incident on inside of surface
    6486              :     //                      Jan 2004, FW: for blinds with horizontal slats, allow different diffuse/diffuse
    6487              :     //                                    transmittance for ground and sky solar
    6488              :     //                      Apr 2004, FW: allow diffusing glazing
    6489              :     //                      May 2006, RR: allow external window screen
    6490              :     //                      Jan 2010, TH: add calculating and reporting of WinBmBmSolar, WinBmDifSolar,
    6491              :     //                                    WinBmBmSolarEnergy, and WinBmDifSolarEnergy
    6492              :     //                      Jun 2013, SV: scheduled surface gains for walls and windows
    6493              : 
    6494              :     // PURPOSE OF THIS SUBROUTINE:
    6495              :     // For a time step, calculates solar radiation absorbed by exterior
    6496              :     // surfaces and interior solar radiation distribution
    6497              : 
    6498              :     using Dayltg::TransTDD;
    6499              :     using namespace DataWindowEquivalentLayer;
    6500              : 
    6501        71220 :     Array1D<Real64> CFBoverlap;    // Sum of boverlap for each back surface
    6502        71220 :     Array2D<Real64> CFDirBoverlap; // Directional boverlap (Direction, IBack)
    6503              : 
    6504        71220 :     auto &s_mat = state.dataMaterial;
    6505        71220 :     auto &s_surf = state.dataSurface;
    6506              : 
    6507              : #ifdef EP_Count_Calls
    6508              :     ++state.dataTimingsData->NumIntSolarDist_Calls;
    6509              : #endif
    6510              : 
    6511       170529 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    6512       211324 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    6513       112015 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    6514       112015 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
    6515       112015 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
    6516       143129 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
    6517       248912 :                 for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
    6518       217798 :                     s_surf->SurfWinA(SurfNum, lay) = 0.0;
    6519              :                 }
    6520        31114 :                 state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum) = 0.0;
    6521        31114 :                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = 0.0;
    6522              :             }
    6523       112015 :             int const firstSurfOpaque = thisSpace.OpaqOrIntMassSurfaceFirst;
    6524       112015 :             int const lastSurfOpaque = thisSpace.OpaqOrIntMassSurfaceLast;
    6525       692595 :             for (int SurfNum = firstSurfOpaque; SurfNum <= lastSurfOpaque; ++SurfNum) {
    6526       580580 :                 s_surf->SurfOpaqAI(SurfNum) = 0.0;
    6527       580580 :                 s_surf->SurfOpaqAO(SurfNum) = 0.0;
    6528              :             }
    6529        99309 :         }
    6530              :     }
    6531              : 
    6532        71220 :     if ((int)state.dataDaylightingDevicesData->TDDPipe.size() > 0) {
    6533            0 :         for (auto &e : state.dataDaylightingDevicesData->TDDPipe) {
    6534            0 :             int SurfDome = e.Dome;
    6535            0 :             for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
    6536            0 :                 s_surf->SurfWinA(SurfDome, lay) = 0.0;
    6537              :             }
    6538            0 :             state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfDome) = 0.0;
    6539            0 :             state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfDome) = 0.0;
    6540              :         }
    6541              :     }
    6542              : 
    6543       176530 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    6544              :         // Solar entering a zone as beam or diffuse radiation, originating as beam solar incident on exterior windows)/(Beam normal solar) [W/(W/m2)]
    6545       105310 :         Real64 BTOTZone = 0.0;
    6546              :         // Beam radiation from exterior windows absorbed in a zone or transmitted through
    6547       105310 :         Real64 BABSZone = 0.0;
    6548       105310 :         state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    6549       105310 :         state.dataHeatBal->EnclSolDBSSG(enclosureNum) = 0.0;
    6550       105310 :         state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
    6551              :         // Loop over exterior surfaces in this zone
    6552       105310 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
    6553              :         // delete values from previous timestep
    6554       105310 :         if (state.dataHeatBal->AnyBSDF) {
    6555            0 :             s_surf->SurfWinACFOverlap = 0.0;
    6556              :         }
    6557              : 
    6558              :         //-------------------------------------------------------------------------
    6559              :         // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
    6560              :         //-------------------------------------------------------------------------
    6561              :         // TODO: use opaq and window loop after airboundary is sorted
    6562              :         // TODO: It may be useful to sort SurfacePtr to group windows and domes together to reduce if conditions
    6563       716999 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    6564       611689 :             if (s_surf->Surface(SurfNum).Class != SurfaceClass::Window && s_surf->Surface(SurfNum).Class != SurfaceClass::TDD_Dome) {
    6565       580573 :                 if (!s_surf->Surface(SurfNum).HeatTransSurf) {
    6566            0 :                     continue;
    6567              :                 }
    6568       580573 :                 if (!s_surf->Surface(SurfNum).ExtSolar) {
    6569       232447 :                     continue;
    6570              :                 }
    6571       348126 :                 int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    6572       348126 :                 Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
    6573       348126 :                 Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
    6574       348126 :                 s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
    6575              :             }
    6576              :         }
    6577              : 
    6578              :         //--------------------------------------------------------------------------------------------------------
    6579              :         // EXTERIOR WINDOWS OR TDD DOMES
    6580              :         //--------------------------------------------------------------------------------------------------------
    6581       716999 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    6582       611689 :             auto &surf = s_surf->Surface(SurfNum);
    6583       611689 :             if (surf.Class != SurfaceClass::Window && surf.Class != SurfaceClass::TDD_Dome) {
    6584       580573 :                 continue;
    6585              :             }
    6586        31116 :             if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    6587            0 :                 continue;
    6588              :             }
    6589              : 
    6590        31116 :             auto &surfWin = s_surf->SurfaceWindow(SurfNum);
    6591        31116 :             int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    6592        31116 :             int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
    6593        31116 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    6594        31116 :             int ScNum = surfWin.screenNum;
    6595        31116 :             WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum); // Set in subr. WindowShadingManager
    6596              : 
    6597        31116 :             auto &surfShade = s_surf->surfShades(SurfNum);
    6598              : 
    6599        31116 :             Real64 ProfAng = 0.0; // Window solar profile angle (radians)
    6600              : 
    6601        31116 :             Real64 SlatAng = surfShade.blind.slatAng;
    6602        31116 :             int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    6603        31116 :             int SurfNum2 = SurfNum;
    6604        31116 :             if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    6605            0 :                 SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    6606              :             }
    6607        31116 :             Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    6608        31116 :             Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    6609              : 
    6610              :             //-----------------------------------------
    6611              :             // BLOCK 1
    6612              :             // EXTERIOR BEAM AND DIFFUSE SOLAR RADIATION ABSORBED IN THE GLASS LAYERS OF (SurfWinA)
    6613              :             // EXTERIOR BEAM ABSORBED BY SHADING DEVICE (SurfWinExtBeamAbsByShadFac)
    6614              :             //-----------------------------------------
    6615              :             // Somewhat of a kludge
    6616        31116 :             if (surf.Class == SurfaceClass::TDD_Dome || surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    6617            0 :                 state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) =
    6618              :                     SunLitFract; // Frames/dividers not allow
    6619              :             }
    6620        31116 :             int FenSolAbsPtr = 0;
    6621        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    6622            0 :                 FenSolAbsPtr = WindowScheduledSolarAbs(state, SurfNum, ConstrNum);
    6623              :             }
    6624              :             bool SunlitFracWithoutReveal =
    6625        31116 :                 state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) > 0;
    6626              : 
    6627              :             // Calculate interpolated blind properties
    6628              :             Real64 FrontDiffDiffTrans; // Bare-blind front diffuse-diffuse solar transmittance
    6629              :             Real64 FrontDiffDiffRefl;
    6630              :             Real64 FrontDiffAbs;      // Bare-blind front diffuse solar reflectance
    6631              :             Real64 BackDiffDiffTrans; // Bare-blind back diffuse-diffuse solar transmittance
    6632              :             Real64 BackDiffDiffRefl;
    6633              :             Real64 BackDiffAbs; // Bare-blind back diffuse solar reflectance
    6634              : 
    6635              :             Real64 FrontBeamDiffTrans; // Blind ProfileAnglesolar front beam-diffuse transmittance
    6636              :             Real64 BackBeamDiffTrans;  // Blind solar back beam-diffuse transmittance
    6637              :             Real64 FrontBeamDiffRefl;  // Blind solar front beam-diffuse reflectance
    6638              :             Real64 BackBeamDiffRefl;   // Blind solar back beam-diffuse reflectance
    6639              :             Real64 FrontBeamAbs;       // Blind solar front beam absorptance
    6640              :             Real64 BackBeamAbs;        // Blind solar back beam absorptance
    6641              : 
    6642        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL && ANY_BLIND(ShadeFlag)) {
    6643            0 :                 auto const &surfShade = s_surf->surfShades(SurfNum);
    6644            0 :                 auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    6645            0 :                 assert(matBlind != nullptr);
    6646              : 
    6647            0 :                 int profIdxLo = surfShade.blind.profAngIdxLo;
    6648            0 :                 int profIdxHi = surfShade.blind.profAngIdxHi;
    6649            0 :                 Real64 profInterpFac = surfShade.blind.profAngInterpFac;
    6650              : 
    6651            0 :                 FrontDiffDiffTrans = surfShade.blind.TAR.Sol.Ft.Df.Tra;
    6652              : 
    6653            0 :                 if (SunLitFract > 0.0 || SunlitFracWithoutReveal) {
    6654            0 :                     auto const &btar1 = surfShade.blind.TAR;
    6655            0 :                     auto const &btarFront1Lo = btar1.Sol.Ft.Bm[profIdxLo];
    6656            0 :                     auto const &btarFront1Hi = btar1.Sol.Ft.Bm[profIdxHi];
    6657              : 
    6658            0 :                     FrontBeamAbs = Interp(btarFront1Lo.Abs, btarFront1Hi.Abs, profInterpFac);
    6659            0 :                     FrontBeamDiffTrans = Interp(btarFront1Lo.DfTra, btarFront1Hi.DfTra, profInterpFac);
    6660            0 :                     if (ShadeFlag != WinShadingType::ExtBlind) { // FRONT: interior or bg blinds
    6661            0 :                         FrontDiffDiffRefl = btar1.Sol.Ft.Df.Ref;
    6662            0 :                         FrontDiffAbs = btar1.Sol.Ft.Df.Abs;
    6663            0 :                         FrontBeamDiffRefl = Interp(btarFront1Lo.DfRef, btarFront1Hi.DfRef, profInterpFac);
    6664              :                     }
    6665              : 
    6666            0 :                     if (ShadeFlag != WinShadingType::IntBlind) { // BACK: exterior or bg blinds{
    6667            0 :                         BackDiffDiffTrans = btar1.Sol.Bk.Df.Tra;
    6668            0 :                         BackDiffDiffRefl = btar1.Sol.Bk.Df.Ref;
    6669            0 :                         BackDiffAbs = btar1.Sol.Bk.Df.Abs;
    6670              : 
    6671            0 :                         auto const &btarBack1Lo = btar1.Sol.Bk.Bm[profIdxLo];
    6672            0 :                         auto const &btarBack1Hi = btar1.Sol.Bk.Bm[profIdxHi];
    6673              : 
    6674            0 :                         BackBeamDiffTrans = Interp(btarBack1Lo.DfTra, btarBack1Hi.DfTra, profInterpFac);
    6675            0 :                         BackBeamDiffRefl = Interp(btarBack1Lo.DfRef, btarBack1Hi.DfRef, profInterpFac);
    6676            0 :                         BackBeamAbs = Interp(btarBack1Lo.Abs, btarBack1Hi.Abs, profInterpFac);
    6677              :                     }
    6678              :                 } // if (SunLitFrac > 0.0)
    6679              :             } // if (ANY_BLIND)
    6680              : 
    6681        31116 :             if (SunlitFracWithoutReveal) {
    6682              : 
    6683        16090 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
    6684              : 
    6685              :                     // For bare glazing or switchable glazing, the following includes the effects of
    6686              :                     // (1) diffuse solar produced by beam solar incident on the outside and inside reveal
    6687              :                     // surfaces, and (2) absorption of beam solar by outside and inside reveal surfaces.
    6688              :                     // If there is an exterior shade/blind both of these effects are ignored. If there
    6689              :                     // is an interior or between-glass shade/blind the effects of beam incident on
    6690              :                     // inside reveal surfaces is ignored.
    6691        15305 :                     int NGlass = thisConstruct.TotGlassLayers;
    6692        15305 :                     Array1D<Real64> AbWin(NGlass); // Factor for front beam radiation absorbed in window glass layer
    6693        33750 :                     for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6694        36890 :                         AbWin(Lay) = Window::POLYF(CosInc, thisConstruct.AbsBeamCoef(Lay)) * CosInc * SunLitFract *
    6695        18445 :                                      s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
    6696              :                     }
    6697        15305 :                     if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
    6698              :                         // (ShadeFlag <= 0 || ShadeFlag >= 10) - Bare window (ShadeFlag = -1 or 0 or shading device of off)
    6699        33750 :                         for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6700              :                             // Add contribution of beam reflected from outside and inside reveal
    6701        36890 :                             s_surf->SurfWinA(SurfNum, Lay) = AbWin(Lay) +
    6702        18445 :                                                              s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiff(Lay) +
    6703        18445 :                                                              s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiffBack(Lay);
    6704              :                         }
    6705              :                     } else {
    6706              :                         // Shade, screen, blind or switchable glazing on (ShadeFlag > 0)
    6707              :                         Real64 FracSunLit =
    6708            0 :                             SunLitFract * s_surf->SurfaceWindow(SurfNum)
    6709            0 :                                               .OutProjSLFracMult[state.dataGlobal->HourOfDay]; // Effective fraction of window that is sunlit;
    6710            0 :                         Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    6711            0 :                         Array1D<Real64> AbWinSh(NGlass);    // Like AbWin, but for shaded window
    6712            0 :                         Array1D<Real64> ADiffWinSh(NGlass); // Diffuse solar absorptance of glass layer, window with shading device
    6713            0 :                         if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
    6714            0 :                             FracSunLit = SunLitFract;
    6715              :                         }
    6716              : 
    6717            0 :                         if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
    6718            0 :                             auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
    6719              :                             // Shade or switchable glazing on
    6720            0 :                             for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6721            0 :                                 AbWinSh(Lay) = Window::POLYF(CosInc, thisConstructSh.AbsBeamCoef(Lay)) * CosInc * FracSunLit;
    6722            0 :                                 ADiffWinSh(Lay) = thisConstructSh.AbsDiff(Lay);
    6723              :                             }
    6724            0 :                             if (ShadeFlag == WinShadingType::IntShade) { // Exterior beam absorbed by INTERIOR SHADE
    6725              :                                 // Note that AbsBeamShadeCoef includes effect of shade/glazing inter-reflection
    6726            0 :                                 Real64 AbsShade = Window::POLYF(CosInc,
    6727            0 :                                                                 thisConstructSh.AbsBeamShadeCoef); // Interior shade or blind beam solar absorptance
    6728            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6729            0 :                                     (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
    6730            0 :                                      s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade) *
    6731            0 :                                     surfWin.glazedFrac;
    6732              :                                 // In the above, GlazedFrac corrects for shadowing of divider onto interior shade
    6733            0 :                             } else if (ShadeFlag == WinShadingType::ExtShade) { // Exterior beam absorbed by EXTERIOR SHADE
    6734            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = thisConstructSh.AbsDiffShade * CosInc * SunLitFract;
    6735            0 :                             } else if (ShadeFlag == WinShadingType::BGShade) { // Exterior beam absorbed by BETWEEN-GLASS SHADE
    6736            0 :                                 Real64 AbsShade = Window::POLYF(CosInc, thisConstructSh.AbsBeamShadeCoef);
    6737            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6738            0 :                                     AbsShade * CosInc * SunLitFract +
    6739            0 :                                     s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade;
    6740              :                             }
    6741              : 
    6742              :                         } else {
    6743              :                             // Blind or screen on
    6744            0 :                             ProfAng = surfShade.blind.profAng;
    6745            0 :                             if (ShadeFlag == WinShadingType::IntBlind) {
    6746              :                                 // Interior blind on
    6747            0 :                                 Real64 TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);
    6748            0 :                                 Real64 RGlDiffBack = thisConstruct.ReflectSolDiffBack; // Glazing system back diffuse solar reflectance
    6749            0 :                                 Real64 RhoBlFront = FrontBeamDiffRefl;                 // Blind solar front beam reflectance
    6750            0 :                                 Real64 RhoBlDiffFront = FrontDiffDiffRefl;             // Blind solar front diffuse reflectance
    6751            0 :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6752            0 :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay);        // Diffuse solar absorptance of glass layer, bare window
    6753            0 :                                     Real64 AGlDiffBack = thisConstruct.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
    6754            0 :                                     AbWinSh(Lay) =
    6755            0 :                                         AbWin(Lay) + (TBmBm * AGlDiffBack * RhoBlFront / (1.0 - RhoBlFront * RGlDiffBack)) * CosInc * FracSunLit;
    6756            0 :                                     ADiffWinSh(Lay) =
    6757            0 :                                         ADiffWin + thisConstruct.TransDiff * AGlDiffBack * RhoBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack);
    6758              :                                 }
    6759              :                                 // Exterior beam absorbed by INTERIOR BLIND
    6760              : 
    6761            0 :                                 Real64 AbsBlFront = FrontBeamAbs;     // Blind solar front beam absorptance
    6762            0 :                                 Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
    6763            0 :                                 Real64 AbsShade =
    6764            0 :                                     TBmBm * (AbsBlFront + RhoBlFront * RGlDiffBack * AbsBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack));
    6765            0 :                                 Real64 AbsShadeDiff =
    6766            0 :                                     thisConstruct.TransDiff *
    6767            0 :                                     (AbsBlDiffFront + RhoBlDiffFront * RGlDiffBack * AbsBlDiffFront /
    6768            0 :                                                           (1.0 - RhoBlDiffFront * RGlDiffBack)); // Interior shade or blind diffuse solar absorptance
    6769              : 
    6770            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6771            0 :                                     (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
    6772            0 :                                      s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff) *
    6773            0 :                                     surfWin.glazedFrac;
    6774              : 
    6775              :                                 // In the above, GlazedFrac corrects for shadowing of divider onto interior blind
    6776            0 :                             } else if (ShadeFlag == WinShadingType::ExtBlind) {
    6777              :                                 // Exterior blind on
    6778            0 :                                 Real64 TBlBmBm = surfShade.blind.bmBmTrans; // Blind solar front beam-beam transmittance
    6779            0 :                                 Real64 TBlDifDif = FrontDiffDiffTrans;      // Diffuse-diffuse solar transmittance of blind
    6780            0 :                                 Real64 TBlBmDiff = FrontBeamDiffTrans;      // Blind solar front beam-diffuse transmittance
    6781            0 :                                 Real64 RhoBlBack = BackBeamDiffRefl;        // Blind solar back beam-diffuse reflectance
    6782            0 :                                 Real64 RhoBlDiffBack = BackDiffDiffRefl;    // Blind solar back diffuse reflectance
    6783              :                                 Real64 RGlFront =
    6784            0 :                                     Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
    6785            0 :                                 Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront;       // Glazing system front diffuse solar reflectance
    6786            0 :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6787            0 :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay);     // Diffuse solar absorptance of glass layer, bare window
    6788            0 :                                     Real64 AGlDiffFront = thisConstruct.AbsDiff(Lay); // Glass layer front diffuse solar absorptance
    6789            0 :                                     AbWinSh(Lay) = TBlBmBm * AbWin(Lay) + ((TBlBmBm * RGlFront * RhoBlBack + TBlBmDiff) * AGlDiffFront /
    6790            0 :                                                                            (1 - RGlDiffFront * RhoBlDiffBack)) *
    6791            0 :                                                                               CosInc * FracSunLit;
    6792              :                                     // ADiffWinSh = 0.0  ! Assumes no contribution from reveal reflection when exterior blind in place
    6793              :                                     // Replaced above line with (FCW, 2/10/03):
    6794            0 :                                     ADiffWinSh(Lay) = ADiffWin * TBlDifDif / (1.0 - RGlDiffFront * RhoBlDiffBack);
    6795              :                                 }
    6796              :                                 // Exterior beam absorbed by EXTERIOR BLIND
    6797            0 :                                 Real64 AbsBlFront = FrontBeamAbs;
    6798            0 :                                 Real64 AbsBlBack = BackBeamAbs;     // Blind solar back beam absorptance
    6799            0 :                                 Real64 AbsBlDiffBack = BackDiffAbs; // Blind solar back diffuse absorptance
    6800            0 :                                 Real64 AbsShade = AbsBlFront + AbsBlBack * RGlFront * TBlBmBm +
    6801            0 :                                                   (AbsBlDiffBack * RGlDiffFront / (1.0 - RhoBlDiffBack * RGlDiffFront)) *
    6802            0 :                                                       (RGlFront * TBlBmBm * RhoBlBack + TBlBmDiff);
    6803            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsShade * CosInc * SunLitFract * InOutProjSLFracMult;
    6804            0 :                             } else if (ShadeFlag == WinShadingType::ExtScreen) {
    6805              :                                 // Exterior screen on
    6806            0 :                                 auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    6807            0 :                                 assert(screen != nullptr);
    6808              : 
    6809            0 :                                 auto &surf = s_surf->Surface(SurfNum);
    6810              : 
    6811            0 :                                 Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
    6812            0 :                                 Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
    6813            0 :                                 Real64 winPhi = surf.Tilt * Constant::DegToRad;
    6814            0 :                                 Real64 winTheta = surf.Azimuth * Constant::DegToRad;
    6815            0 :                                 Real64 phi = std::abs(solPhi - winPhi);
    6816            0 :                                 Real64 theta = std::abs(solTheta - winTheta);
    6817            0 :                                 Material::NormalizePhiTheta(phi, theta);
    6818              : #ifdef PRECALC_INTERP_SCREEN
    6819              :                                 int ip1, ip2, it1, it2;
    6820              :                                 BilinearInterpCoeffs coeffs;
    6821            0 :                                 Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
    6822            0 :                                 GetBilinearInterpCoeffs(
    6823            0 :                                     phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
    6824            0 :                                 auto const &b11 = screen->btars[ip1][it1];
    6825            0 :                                 auto const &b12 = screen->btars[ip1][it2];
    6826            0 :                                 auto const &b21 = screen->btars[ip2][it1];
    6827            0 :                                 auto const &b22 = screen->btars[ip2][it2];
    6828              : 
    6829            0 :                                 Real64 TScDifDif = screen->DfTrans;
    6830            0 :                                 Real64 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
    6831            0 :                                 Real64 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
    6832            0 :                                 Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    6833            0 :                                 Real64 RScDifBack = screen->DfRef;
    6834              : 
    6835              :                                 Real64 RGlFront =
    6836            0 :                                     Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
    6837            0 :                                 Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront;       // Glazing system front diffuse solar reflectance
    6838            0 :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;           // Diffuse front reflectance of glass
    6839              :                                 // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
    6840              :                                 // interreflections
    6841            0 :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6842            0 :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
    6843            0 :                                     AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
    6844            0 :                                                                               (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
    6845            0 :                                     ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
    6846              :                                 }
    6847              :                                 // Exterior beam absorbed by EXTERIOR SCREEN
    6848            0 :                                 Real64 AbsScBeam = BilinearInterp(b11.AbsSolFront, b12.AbsSolFront, b21.AbsSolFront, b22.AbsSolFront, coeffs);
    6849            0 :                                 Real64 AbsScDiffBack = screen->DfAbs;
    6850            0 :                                 Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
    6851            0 :                                                    (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
    6852            0 :                                                     (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
    6853            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
    6854              : #else  // !PRECALC_INTERP_SCREEN
    6855              :                                 Material::ScreenBmTransAbsRef btar;
    6856              :                                 CalcScreenTransmittance(state, screen, phi, theta, btar);
    6857              : 
    6858              :                                 Real64 TScDifDif = screen->DfTrans;
    6859              :                                 Real64 TScBmDif = btar.DfTrans;
    6860              :                                 Real64 TScBmBm = btar.BmTrans;
    6861              :                                 Real64 RScBack = btar.RefSolFront;
    6862              :                                 Real64 RScDifBack = screen->DfRef;
    6863              : 
    6864              :                                 Real64 RGlFront =
    6865              :                                     Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
    6866              :                                 Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront;       // Glazing system front diffuse solar reflectance
    6867              :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;           // Diffuse front reflectance of glass
    6868              :                                 // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
    6869              :                                 // interreflections
    6870              :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6871              :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
    6872              :                                     AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
    6873              :                                                                               (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
    6874              :                                     ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
    6875              :                                 }
    6876              :                                 // Exterior beam absorbed by EXTERIOR SCREEN
    6877              :                                 Real64 AbsScBeam = btar.AbsSolFront;
    6878              :                                 Real64 AbsScDiffBack = screen->DfAbs;
    6879              :                                 Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
    6880              :                                                    (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
    6881              :                                                     (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
    6882              :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
    6883              : #endif // PRECALC_INTERP_SCREEN
    6884            0 :                             } else if (ShadeFlag == WinShadingType::BGBlind) {
    6885              :                                 // Between-glass blind o
    6886              :                                 // Isolated glass and blind properties at current incidence angle, profile angle and slat angle
    6887            0 :                                 Real64 t1 = Window::POLYF(CosInc,
    6888            0 :                                                           thisConstruct.tBareSolCoef(1)); // Bare-glass beam solar trans for glass layers 1,2 and 3
    6889            0 :                                 Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
    6890              :                                 Real64 af1 =
    6891            0 :                                     Window::POLYF(CosInc,
    6892            0 :                                                   thisConstruct.afBareSolCoef(1)); // Bare-glass beam solar front abs for glass layers 1,2 and 3
    6893            0 :                                 Real64 af2 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(2));
    6894            0 :                                 Real64 ab1 = Window::POLYF(
    6895              :                                     CosInc,
    6896            0 :                                     thisConstruct.abBareSolCoef(1)); // Bare-glass beam solar back absorptance for glass layers 1,2 and 3
    6897            0 :                                 Real64 ab2 = Window::POLYF(CosInc, thisConstruct.abBareSolCoef(2));
    6898            0 :                                 Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
    6899            0 :                                 Real64 td1 = thisConstruct.tBareSolDiff(1); // Bare-glass diffuse solar transmittance for glass layers 1,2 and 3
    6900            0 :                                 Real64 td2 = thisConstruct.tBareSolDiff(2);
    6901            0 :                                 Real64 afd1 = thisConstruct.afBareSolDiff(1); // Bare-glass diffuse solar front absorptance for glass layers 1,2 and 3
    6902            0 :                                 Real64 afd2 = thisConstruct.afBareSolDiff(2);
    6903            0 :                                 Real64 abd1 = thisConstruct.abBareSolDiff(1); // Bare-glass diffuse solar back absorptance for glass layers 1,2 and 3
    6904            0 :                                 Real64 abd2 = thisConstruct.abBareSolDiff(2);
    6905            0 :                                 Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
    6906            0 :                                 Real64 rbd1 = thisConstruct.rbBareSolDiff(1); // Bare-glass diffuse solar back reflectance for glass layers 1,2 and 3
    6907            0 :                                 Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
    6908            0 :                                 Real64 tfshBB = surfShade.blind.bmBmTrans; // Bare-blind front and back beam-beam solar transmittance
    6909              : 
    6910            0 :                                 auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    6911            0 :                                 assert(matBlind != nullptr);
    6912            0 :                                 Real64 tbshBB = matBlind->BeamBeamTrans(ProfAng, Constant::Pi - SlatAng);
    6913            0 :                                 Real64 tfshBd = FrontBeamDiffTrans; // Bare-blind front and back beam-diffuse solar transmittance
    6914            0 :                                 Real64 tbshBd = BackBeamDiffTrans;
    6915            0 :                                 Real64 rfshB = FrontBeamDiffRefl; // Bare-blind front and back beam solar reflectance
    6916            0 :                                 Real64 rbshB = BackBeamDiffRefl;
    6917            0 :                                 Real64 afshB = FrontBeamAbs;
    6918            0 :                                 Real64 abshB = BackBeamAbs;
    6919              : 
    6920            0 :                                 Real64 tfshd = FrontDiffDiffTrans; // Bare-blind front and back diffuse-diffuse solar transmittance
    6921            0 :                                 Real64 tbshd = BackDiffDiffTrans;
    6922            0 :                                 Real64 rfshd = FrontDiffDiffRefl; // Bare-blind front and back diffuse solar reflectance
    6923            0 :                                 Real64 rbshd = BackDiffDiffRefl;
    6924            0 :                                 Real64 afshd = FrontDiffAbs;
    6925            0 :                                 Real64 abshd = BackDiffAbs;
    6926              : 
    6927            0 :                                 Real64 AbsShade = 0.0;
    6928            0 :                                 Real64 AbsShadeDiff = 0.0;
    6929            0 :                                 if (NGlass == 2) {
    6930            0 :                                     AbWinSh(1) = CosInc * FracSunLit *
    6931            0 :                                                  (af1 + t1 * tfshBB * rf2 * tbshBB * ab1 +
    6932            0 :                                                   t1 * (rfshB + rfshB * rbd1 * rfshd + tfshBB * rf2 * tbshBd + tfshBd * rfd2 * tbshd) * abd1);
    6933            0 :                                     ADiffWinSh(1) = afd1 + td1 * (rfshd + rfshd * rbd1 * rfshd + tfshd * rfd2 * tbshd) * abd1;
    6934            0 :                                     AbWinSh(2) =
    6935            0 :                                         CosInc * FracSunLit *
    6936            0 :                                         (t1 * rfshB * af2 + t1 * (rfshB * rf2 * rbshd + tfshBd * (1 + rfd2 * rbshd) + rfshB * rbd1 * tfshd) * afd2);
    6937            0 :                                     ADiffWinSh(2) = td1 * (tfshd * (1 + rfd2 * rbshd) + rfshd * rbd1 * tfshd) * afd2;
    6938            0 :                                     AbsShade = t1 * (afshB + tfshBB * rf2 * abshB + tfshBd * rfd2 * abshd + rfshB * rbd1 * afshd);
    6939            0 :                                     AbsShadeDiff = td1 * (afshd * (1 + rfshd * rbd1) + tfshd * rfd2 * abshd);
    6940            0 :                                 } else if (NGlass == 3) {
    6941            0 :                                     Real64 t1t2 = t1 * t2; // t1*t2
    6942            0 :                                     Real64 td1td2 = td1 * td2;
    6943            0 :                                     Real64 af3 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(3));
    6944            0 :                                     Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
    6945            0 :                                     Real64 afd3 = thisConstruct.afBareSolDiff(3);
    6946            0 :                                     Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
    6947            0 :                                     Real64 td2 = thisConstruct.tBareSolDiff(2);
    6948            0 :                                     AbWinSh(1) = CosInc * FracSunLit *
    6949            0 :                                                  (af1 + t1 * rf2 * ab1 + t1t2 * tfshBB * rf3 * tbshBB * t2 * ab1 +
    6950            0 :                                                   t1t2 * (rfshB * td2 + rfshB * rbd2 * rfshd * td2 + tfshBd * rfd3 * tbshd * td2) * abd1);
    6951            0 :                                     ADiffWinSh(1) = afd1 + td1 * rbd2 * abd1 +
    6952            0 :                                                     td1td2 *
    6953            0 :                                                         (rfshd * (1 + rbd2 * rfshd + td2 * rbd1 * td2 * rfshd) +
    6954            0 :                                                          tfshd * (rfd3 * tbshd + rfd3 * rbshd * rfd3 * tbshd)) *
    6955            0 :                                                         td2 * abd1;
    6956            0 :                                     AbWinSh(2) = CosInc * FracSunLit *
    6957            0 :                                                  (t1 * af2 + t1t2 * (tfshBB * rf3 * tbshBB * ab2 + rfshB * td2 * rbd1 * afd2) +
    6958            0 :                                                   t1t2 * (rfshB * (1 + rbd2 * rfshd) + tfshBB * rf3 * tbshBd + tfshBd * rfd3 * tbshd) * abd2);
    6959            0 :                                     ADiffWinSh(2) = td1 * afd2 + td1td2 * rfshd * td2 * rbd1 * afd2 +
    6960            0 :                                                     td1td2 * (rfshd * (1 + rbd2 * rfshd) + tfshd * rfd3 * tbshd) * abd2;
    6961            0 :                                     AbWinSh(3) = CosInc * FracSunLit *
    6962            0 :                                                  (t1t2 * tfshBB * af3 + t1t2 *
    6963            0 :                                                                             (tfshBB * rf3 * rbshB + tfshBd * (1 + rfd3 * rbshd) +
    6964            0 :                                                                              rfshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
    6965              :                                                                             afd3);
    6966            0 :                                     ADiffWinSh(3) = td1td2 * (tfshd * (1 + rfd3 * rbshd) + rfshd * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) * afd3;
    6967            0 :                                     AbsShade = t1t2 * (afshB * (1 + tfshBB * rf3) + afshd * (tfshBd * rfd3 + rfshB * (rbd2 + td2 * rbd1 * td2)));
    6968            0 :                                     AbsShadeDiff = td1td2 * (afshd + tfshd * rfd3 * abshd + rfshd * (rfd2 + td2 * rbd2 * td2) * afshd);
    6969              :                                 } // End of check if NGlass
    6970            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6971            0 :                                     AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
    6972            0 :                                     s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff;
    6973              :                             } // End of check if blind is interior, exterior or between-glass
    6974              :                         } // End of check if a blind is on
    6975              : 
    6976            0 :                         if (ShadeFlag != WinShadingType::SwitchableGlazing) {
    6977              :                             // Interior or between glass shade or blind on
    6978            0 :                             for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6979            0 :                                 s_surf->SurfWinA(SurfNum, Lay) = AbWinSh(Lay);
    6980              :                                 // Add contribution of diffuse from beam on outside reveal
    6981            0 :                                 if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag) || ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag)) {
    6982            0 :                                     s_surf->SurfWinA(SurfNum, Lay) += ADiffWinSh(Lay) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum);
    6983              :                                 }
    6984              :                             }
    6985              :                         } else {
    6986            0 :                             auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
    6987              :                             // Switchable glazing
    6988            0 :                             for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6989            0 :                                 Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
    6990            0 :                                 Real64 ADiffWin = thisConstruct.AbsDiff(Lay);
    6991            0 :                                 s_surf->SurfWinA(SurfNum, Lay) = Window::InterpSw(SwitchFac, AbWin(Lay), AbWinSh(Lay));
    6992              :                                 // Add contribution of diffuse from beam on outside and inside reveal
    6993            0 :                                 s_surf->SurfWinA(SurfNum, Lay) +=
    6994            0 :                                     Window::InterpSw(SwitchFac, ADiffWin, ADiffWinSh(Lay)) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) +
    6995            0 :                                     Window::InterpSw(SwitchFac, thisConstruct.AbsDiffBack(Lay), thisConstructSh.AbsDiffBack(Lay)) *
    6996            0 :                                         s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum);
    6997              :                             }
    6998              :                         }
    6999            0 :                     }
    7000              : 
    7001        16090 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7002              :                     // Do not read from schedule file here since this will be called only if direct beam is hitting the window and schedule
    7003              :                     // will not be loaded in that case even if diffuse part of solar radiation is entering through the window
    7004            0 :                     if (FenSolAbsPtr == 0) {
    7005              :                         // Put in the equivalent layer absorptions
    7006              :                         // Simon: This should not be multiplied with CosInc since Abs coefficient already includes angular
    7007              :                         // factor
    7008            0 :                         for (int Lay = 1;
    7009            0 :                              Lay <= s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).NLayers;
    7010              :                              ++Lay) {
    7011            0 :                             Real64 absBeamWin = s_surf->SurfaceWindow(SurfNum)
    7012            0 :                                                     .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7013            0 :                                                     .WinBmFtAbs(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, Lay);
    7014              :                             Real64 AbWin =
    7015            0 :                                 absBeamWin * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
    7016              : 
    7017              :                             // Add contribution of beam reflected from outside and inside reveal
    7018            0 :                             s_surf->SurfWinA(SurfNum, Lay) = AbWin +
    7019            0 :                                                              s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
    7020            0 :                                                                  s_surf->SurfaceWindow(SurfNum)
    7021            0 :                                                                      .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7022            0 :                                                                      .WinFtHemAbs(Lay) +
    7023            0 :                                                              s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) *
    7024            0 :                                                                  s_surf->SurfaceWindow(SurfNum)
    7025            0 :                                                                      .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7026            0 :                                                                      .WinBkHemAbs(Lay);
    7027              :                         }
    7028              :                     }
    7029              : 
    7030          785 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
    7031              :                     // call the ASHWAT fenestration model for optical properties
    7032              :                     // determine the beam radiation absorptance and transmittance of the
    7033              :                     // the equivalent layer window model
    7034          785 :                     WindowEquivalentLayer::CalcEQLOpticalProperty(state, SurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamEQL);
    7035          785 :                     auto &CFS = state.dataWindowEquivLayer->CFS;
    7036              :                     // recalculate the diffuse absorptance and transmittance of the
    7037              :                     // the equivalent layer window model if there is shade control
    7038          785 :                     int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
    7039          785 :                     if (CFS(EQLNum).ISControlled) {
    7040          320 :                         WindowEquivalentLayer::CalcEQLOpticalProperty(
    7041          320 :                             state, SurfNum, SolarArrays::DIFF, state.dataSolarShading->SurfWinAbsSolDiffEQL);
    7042              :                     } else {
    7043          930 :                         state.dataSolarShading->SurfWinAbsSolDiffEQL(_, {1, CFS(EQLNum).NL + 1}) =
    7044         1395 :                             state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFS(EQLNum).NL + 1}, EQLNum);
    7045              :                     }
    7046          785 :                     thisConstruct.TransDiff = state.dataSolarShading->SurfWinAbsSolDiffEQL(1, CFS(EQLNum).NL + 1);
    7047              : 
    7048         3628 :                     for (int Lay = 1; Lay <= CFS(EQLNum).NL + 1; ++Lay) {
    7049              :                         // Factor for front beam radiation absorbed for equivalent layer window model
    7050         2843 :                         Real64 AbWinEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) * CosInc * SunLitFract *
    7051         2843 :                                           s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    7052              :                         ;
    7053         2843 :                         if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
    7054              :                             // if the first layer is not glazing (or it is a shade) do not
    7055            0 :                             s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL;
    7056              :                         } else {
    7057              :                             // the first layer is a glazing, include the outside reveal reflection
    7058              :                             // and the inside reveal reflection until indoor shade layer is encountered.
    7059         2843 :                             if (CFS(EQLNum).L(Lay).LTYPE == LayerType::GLAZE) {
    7060         1570 :                                 s_surf->SurfWinA(SurfNum, Lay) =
    7061         1570 :                                     AbWinEQL +
    7062         1570 :                                     s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) +
    7063         1570 :                                     s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolDiffEQL(2, Lay);
    7064              :                             } else {
    7065         2546 :                                 s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL + s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
    7066         1273 :                                                                                 state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay);
    7067              :                             }
    7068              :                         }
    7069              :                     }
    7070              :                 }
    7071              :             } // End of SunlitFrac check
    7072              : 
    7073              :             //-----------------------------------------------------------------
    7074              :             // BLOCK 2
    7075              :             // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
    7076              :             //-----------------------------------------------------------------
    7077              : 
    7078              :             Real64 SkySolarInc =
    7079        31116 :                 s_surf->SurfSkySolarInc(SurfNum); // Incident solar radiation on a window: sky diffuse plus beam reflected from obstruction (W/m2)
    7080        31116 :             Real64 DiffTrans = 0.0;               // Glazing diffuse solar transmittance (including shade/blind/switching, if present)
    7081              :             Real64 DiffTransGnd;                  // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    7082              :             Real64 DiffTransBmGnd;                // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
    7083              :             Real64 DiffTransSky;                  // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    7084        31116 :             Real64 NomDiffTrans = 0.0;
    7085              : 
    7086        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // complex fenestration
    7087            0 :                 if (FenSolAbsPtr == 0) {
    7088              :                     // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    7089            0 :                     DiffTransSky =
    7090            0 :                         s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyTrans;
    7091              :                     // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    7092            0 :                     DiffTransGnd =
    7093            0 :                         s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyGndTrans;
    7094              :                     // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
    7095            0 :                     DiffTransBmGnd = s_surf->SurfaceWindow(SurfNum)
    7096            0 :                                          .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7097            0 :                                          .WinBmGndTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    7098              :                     // Define the effective transmittance for total sky and ground radiation
    7099            0 :                     if ((SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum)) != 0.0) {
    7100            0 :                         DiffTrans = (SkySolarInc * DiffTransSky + s_surf->SurfWinBmGndSolarInc(SurfNum) * DiffTransBmGnd +
    7101            0 :                                      s_surf->SurfWinSkyGndSolarInc(SurfNum) * DiffTransGnd) /
    7102            0 :                                     (SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum));
    7103              :                     }
    7104              :                     // Also update the nominal diffuse transmittance
    7105            0 :                     NomDiffTrans =
    7106            0 :                         s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
    7107              :                     // Do not store in TransDiff because it is not used by BSDF and rest of the code uses it as flag for opaque
    7108              :                     // surface incorrectly assuming wall heat transfer routines for windows.
    7109              :                     // Construct( Surface( SurfNum ).Construction ).TransDiff = NomDiffTrans;
    7110              :                 }
    7111        31116 :             } else if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    7112            0 :                 DiffTrans = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
    7113              :             } else {
    7114        31116 :                 DiffTrans = thisConstruct.TransDiff;
    7115              :             }
    7116              : 
    7117        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
    7118        29742 :                 if (IS_SHADED_NO_GLARE_CTRL(s_surf->SurfWinShadingFlag(SurfNum))) {
    7119            0 :                     auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
    7120            0 :                     if (ShadeFlag != WinShadingType::SwitchableGlazing) {
    7121              :                         // Shade or blind
    7122            0 :                         if (ANY_SHADE_SCREEN(ShadeFlag)) {
    7123              :                             // Shade or screen
    7124            0 :                             DiffTrans = constrSh.TransDiff;
    7125              :                         } else {
    7126              :                             // Blind
    7127            0 :                             int slatIdxLo = surfShade.blind.slatAngIdxLo;
    7128            0 :                             int slatIdxHi = surfShade.blind.slatAngIdxHi;
    7129            0 :                             Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
    7130              : 
    7131            0 :                             auto const &btarLo = constrSh.blindTARs[slatIdxLo];
    7132            0 :                             auto const &btarHi = constrSh.blindTARs[slatIdxHi];
    7133              : 
    7134            0 :                             DiffTrans = Interp(btarLo.Sol.Ft.Df.Tra, btarHi.Sol.Ft.Df.Tra, slatInterpFac);
    7135              : 
    7136              :                             // For blinds with horizontal slats, allow different diffuse/diffuse transmittance for
    7137              :                             // ground and sky solar
    7138            0 :                             auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    7139            0 :                             assert(matBlind != nullptr);
    7140            0 :                             if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
    7141            0 :                                 DiffTransGnd = Interp(btarLo.Sol.Ft.Df.TraGnd, btarHi.Sol.Ft.Df.TraGnd, slatInterpFac);
    7142            0 :                                 DiffTransSky = Interp(btarLo.Sol.Ft.Df.TraSky, btarHi.Sol.Ft.Df.TraSky, slatInterpFac);
    7143              :                             }
    7144              :                         }
    7145              : 
    7146              :                     } else { // Switchable glazing
    7147              : 
    7148            0 :                         Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
    7149            0 :                         DiffTrans = Window::InterpSw(SwitchFac, thisConstruct.TransDiff, constrSh.TransDiff);
    7150              :                     }
    7151              :                 }
    7152              :             }
    7153              : 
    7154              :             // Reporting variables
    7155        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
    7156        29742 :                 s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
    7157        29742 :                 s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
    7158        29742 :                 if (ANY_BLIND(ShadeFlag) || ShadeFlag == WinShadingType::ExtScreen) {
    7159            0 :                     s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
    7160            0 :                     s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
    7161            0 :                     if (ShadeFlag == WinShadingType::ExtScreen) {
    7162            0 :                         auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    7163            0 :                         assert(screen != nullptr);
    7164            0 :                         s_surf->SurfWinScTsolDifDif(SurfNum) = screen->DfTrans;
    7165              :                     } else {
    7166            0 :                         s_surf->SurfWinBlTsolDifDif(SurfNum) = FrontDiffDiffTrans;
    7167              :                     }
    7168              :                 }
    7169              :             }
    7170              : 
    7171              :             //-----------------------------------------------------------------
    7172              :             // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
    7173              :             //-----------------------------------------------------------------
    7174        31116 :             Real64 TBmBm = 0.0;        // Beam-beam solar transmittance for bare window or window with switchable glazing
    7175        31116 :             Real64 TBmDif = 0.0;       // Beam-diffuse solar transmittance for bare window with diffusing glass
    7176        31116 :             Real64 TBmAllShBlSc = 0.0; // Beam-beam + beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
    7177        31116 :             Real64 TBmBmShBlSc = 0.0;  // Beam-beam transmittance for window with shade, blind, screen, or switchable glazing
    7178        31116 :             Real64 TBmDifShBlSc = 0.0; // Beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
    7179              :             Real64 TBmBmBl;            // Beam-beam transmittance for window with blind
    7180              :             Real64 TBmBmSc;            // Beam-beam transmittance for window with screen
    7181              :             Real64 TDifBare;           // Bare diffuse transmittance of exterior window
    7182              :             // Beam-beam transmittance for bare exterior window
    7183        31116 :             if (SunLitFract > 0.0) {
    7184        16092 :                 if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    7185            0 :                     TBmDif = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarBeam);
    7186            0 :                     state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolBeam = TBmDif;  // Report variable
    7187        16092 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) { // Regular window
    7188        15307 :                     if (!s_surf->SurfWinSolarDiffusing(SurfNum)) {                             // Clear glazing
    7189        15307 :                         TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);         //[-]
    7190              :                     } else {                                                                   // Diffusing glazing
    7191            0 :                         TBmDif = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);        //[-]
    7192              :                     }
    7193          785 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7194              :                     // Need to check what effect, if any, defining these here has
    7195            0 :                     TBmBm = s_surf->SurfaceWindow(SurfNum)
    7196            0 :                                 .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7197            0 :                                 .WinDirSpecTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    7198            0 :                     TBmDif = s_surf->SurfaceWindow(SurfNum)
    7199            0 :                                  .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7200            0 :                                  .WinDirHemiTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep) -
    7201              :                              TBmBm;
    7202          785 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
    7203              :                     // get ASHWAT fenestration model beam-beam and beam-diffuse properties
    7204          785 :                     int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
    7205          785 :                     Real64 TBmBmEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1);
    7206              :                     // Beam-diffuse transmittance
    7207          785 :                     Real64 TBmDiffEQL = max(0.0, state.dataSolarShading->SurfWinAbsSolBeamEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1));
    7208              :                     // Beam-beam transmittance: difference between beam-total and beam-diffuse transmittance
    7209          785 :                     TBmBmEQL = max(0.0, (TBmBmEQL - TBmDiffEQL));
    7210          785 :                     TBmBm = TBmBmEQL;
    7211          785 :                     TBmDif = TBmDiffEQL;
    7212              :                 }
    7213              :             }
    7214              :             // Diffuse-diffuse transmittance for bare exterior window
    7215        31116 :             if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    7216            0 :                 TDifBare = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
    7217              :             } else {
    7218        31116 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7219              :                     // Complex Fenestration: use hemispherical ave of directional-hemispherical transmittance
    7220              :                     // Note: this is not quite the same as the effective transmittance for total of sky and ground radiation
    7221            0 :                     TDifBare = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
    7222              :                 } else { // Regular window
    7223        31116 :                     TDifBare = thisConstruct.TransDiff;
    7224              :                 }
    7225              :             }
    7226              : 
    7227              :             //-----------------------------------------------------------------
    7228              :             // BLOCK 3 - SCREEN, BLINDS AND GLAZING SYSTEM BEAM SOLAR TRANSMITTANCE
    7229              :             //-----------------------------------------------------------------
    7230        31116 :             if (ConstrNumSh != 0 && SunLitFract > 0.0) {
    7231         6440 :                 auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
    7232         6440 :                 if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
    7233         6440 :                     if (IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
    7234              :                         // Shade or screen or blind on, or switchable glazing
    7235              :                         // (note in the following that diffusing glass is not oallowed in a window with shade, blind or switchable glazing)
    7236            0 :                         if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
    7237              :                             // Shade on or switchable glazing
    7238            0 :                             TBmAllShBlSc = Window::POLYF(CosInc, thisConstructSh.TransSolBeamCoef);
    7239              :                         } else {
    7240              :                             // Blind or Screen on
    7241              :                             Real64 TScBmDif;  // Beam-diffuse solar transmittance of screen
    7242              :                             Real64 TBlBmDif;  // Beam-diffuse solar transmittance of blind
    7243              :                             Real64 TBlDifDif; // Diffuse-diffuse solar transmittance of blind
    7244              :                             Real64 TScBmBm;
    7245              :                             Real64 TBlBmBm;
    7246            0 :                             if (ShadeFlag == WinShadingType::ExtScreen) { // Exterior screen
    7247            0 :                                 auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    7248            0 :                                 assert(screen != nullptr);
    7249              : 
    7250            0 :                                 auto &surf = s_surf->Surface(SurfNum);
    7251            0 :                                 Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
    7252            0 :                                 Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
    7253            0 :                                 Real64 winPhi = surf.Tilt * Constant::DegToRad;
    7254            0 :                                 Real64 winTheta = surf.Azimuth * Constant::DegToRad;
    7255            0 :                                 Real64 phi = std::abs(solPhi - winPhi);
    7256            0 :                                 Real64 theta = std::abs(solTheta - winTheta);
    7257            0 :                                 Material::NormalizePhiTheta(phi, theta);
    7258              : #ifdef PRECALC_INTERP_SCREEN
    7259              :                                 int ip1, ip2, it1, it2;
    7260              :                                 BilinearInterpCoeffs coeffs;
    7261            0 :                                 Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
    7262            0 :                                 GetBilinearInterpCoeffs(
    7263            0 :                                     phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
    7264            0 :                                 auto const &b11 = screen->btars[ip1][it1];
    7265            0 :                                 auto const &b12 = screen->btars[ip1][it2];
    7266            0 :                                 auto const &b21 = screen->btars[ip2][it1];
    7267            0 :                                 auto const &b22 = screen->btars[ip2][it2];
    7268              : 
    7269            0 :                                 Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    7270            0 :                                 Real64 RScDifBack = screen->DfRef;
    7271              : 
    7272            0 :                                 Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
    7273            0 :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;                        // Diffuse front reflectance of glass
    7274              :                                 // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
    7275            0 :                                 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
    7276            0 :                                 TBmBmSc = TBmBm * TScBmBm;
    7277            0 :                                 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
    7278              :                                 // beam-beam and diffuse transmittance of exterior beam
    7279            0 :                                 TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
    7280            0 :                                                TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
    7281            0 :                                 TBmBmShBlSc = TBmBmSc;
    7282            0 :                                 TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7283              :                                 // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
    7284            0 :                                 s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
    7285            0 :                                 s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
    7286            0 :                                 s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
    7287              : #else  // !PRECALC_INTERP_SCREEN
    7288              :                                 Material::ScreenBmTransAbsRef btar;
    7289              :                                 CalcScreenTransmittance(state, screen, phi, theta, btar);
    7290              : 
    7291              :                                 Real64 RScBack = btar.RefSolFront;
    7292              :                                 Real64 RScDifBack = screen->DfRef;
    7293              : 
    7294              :                                 Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
    7295              :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;                        // Diffuse front reflectance of glass
    7296              :                                 // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
    7297              :                                 TScBmBm = btar.BmTrans;
    7298              :                                 TBmBmSc = TBmBm * TScBmBm;
    7299              :                                 TScBmDif = btar.DfTrans;
    7300              :                                 // beam-beam and diffuse transmittance of exterior beam
    7301              :                                 TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
    7302              :                                                TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
    7303              :                                 TBmBmShBlSc = TBmBmSc;
    7304              :                                 TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7305              :                                 // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
    7306              :                                 s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
    7307              :                                 s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
    7308              :                                 s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
    7309              : #endif // PRECALC_INTERP_SCREEN
    7310              :                             } else {
    7311            0 :                                 TBlBmBm = surfShade.blind.bmBmTrans;
    7312            0 :                                 TBlBmDif = FrontBeamDiffTrans;
    7313            0 :                                 if (ShadeFlag == WinShadingType::IntBlind) {
    7314            0 :                                     Real64 RhoBlBmDifFr = FrontBeamDiffRefl;            // Beam-diffuse front reflectance of blind
    7315            0 :                                     Real64 RGlDifBk = thisConstruct.ReflectSolDiffBack; // Diffuse front reflectance of glass
    7316            0 :                                     Real64 RhoBlDifDifFr = FrontDiffDiffRefl;           // Diffuse-diffuse front reflectance of blind
    7317              :                                     // beam-beam and diffuse transmittance of exterior beam
    7318            0 :                                     TBmBmBl = TBmBm * TBlBmBm;
    7319            0 :                                     TBlDifDif = FrontDiffDiffTrans;
    7320            0 :                                     TBmAllShBlSc =
    7321            0 :                                         TBmBm * (TBlBmBm + TBlBmDif + TBlDifDif * RhoBlBmDifFr * RGlDifBk / (1 - RhoBlDifDifFr * RGlDifBk));
    7322            0 :                                     TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
    7323            0 :                                     TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7324            0 :                                     if (TBmDifShBlSc < 0.0) {
    7325            0 :                                         TBmDifShBlSc = 0.0;
    7326              :                                     }
    7327            0 :                                 } else if (ShadeFlag == WinShadingType::ExtBlind) {
    7328            0 :                                     Real64 RhoBlBmDifBk = BackBeamDiffRefl;  // Beam-diffuse back reflectance of blind
    7329            0 :                                     Real64 RhoBlDifDifBk = BackDiffDiffRefl; // Diffuse-diffuse back reflectance of blind
    7330            0 :                                     Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef);
    7331            0 :                                     Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7332              :                                     // beam-beam and diffuse transmittance of exterior beam
    7333            0 :                                     TBmBmBl = TBmBm * TBlBmBm;
    7334            0 :                                     TBmAllShBlSc = TBlBmBm * (TBmBm + TDifBare * RGlBmFr * RhoBlBmDifBk / (1 - RGlDifFr * RhoBlDifDifBk)) +
    7335            0 :                                                    TBlBmDif * TDifBare / (1 - RGlDifFr * RhoBlDifDifBk);
    7336            0 :                                     TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
    7337            0 :                                     TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7338              :                                 } else {
    7339              :                                     // Between-glass blind on
    7340            0 :                                     int NGlass = thisConstruct.TotGlassLayers;
    7341            0 :                                     Real64 td2 = thisConstruct.tBareSolDiff(2);
    7342            0 :                                     Real64 rbd1 = thisConstruct.rbBareSolDiff(1);
    7343            0 :                                     Real64 rbshB = BackBeamDiffRefl;
    7344            0 :                                     Real64 rfshd = FrontDiffDiffRefl;
    7345            0 :                                     Real64 rbshd = BackDiffDiffRefl;
    7346            0 :                                     Real64 tfshBd = FrontBeamDiffTrans;
    7347            0 :                                     Real64 t1 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(1));
    7348            0 :                                     Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
    7349            0 :                                     Real64 tfshBB = surfShade.blind.bmBmTrans;
    7350            0 :                                     if (NGlass == 2) {
    7351            0 :                                         Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
    7352            0 :                                         Real64 rfshB = FrontBeamDiffRefl;
    7353            0 :                                         Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
    7354            0 :                                         TBmBmBl = t1 * tfshBB * t2;
    7355            0 :                                         TBmAllShBlSc = t1 * tfshBB * t2 +
    7356            0 :                                                        t1 * (tfshBB * rf2 * rbshB + tfshBd * (1.0 + rfd2 * rbshd) + rfshB * rbd1 * rfshd) * td2;
    7357              :                                     } else { // NGlass = 3
    7358            0 :                                         Real64 t1t2 = t1 * t2;
    7359            0 :                                         Real64 t3 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(3));
    7360            0 :                                         Real64 td3 = thisConstruct.tBareSolDiff(3);
    7361            0 :                                         Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
    7362            0 :                                         Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
    7363            0 :                                         Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
    7364            0 :                                         Real64 tfshd = FrontDiffDiffTrans;
    7365            0 :                                         TBmBmBl = t1 * t2 * tfshBB * t3;
    7366            0 :                                         TBmAllShBlSc = t1t2 * tfshBB * t3 + t1t2 *
    7367            0 :                                                                                 (tfshBB * rf3 * rbshB + tfshBd * (1.0 + rfd3 * rbshd) +
    7368            0 :                                                                                  rbshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
    7369              :                                                                                 td3;
    7370              :                                     }
    7371              :                                     // added TH 12/9/2009
    7372            0 :                                     TBmBmShBlSc = TBmBmBl;
    7373            0 :                                     TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7374              :                                 }
    7375            0 :                                 s_surf->SurfWinBlTsolBmBm(SurfNum) = TBlBmBm;
    7376            0 :                                 s_surf->SurfWinBlTsolBmDif(SurfNum) = TBlBmDif;
    7377            0 :                                 s_surf->SurfWinBlGlSysTsolBmBm(SurfNum) = TBmBmBl;
    7378              :                             }
    7379              :                         }
    7380              :                     } // End of check if ShadeFlag > 0 and ShadeFlag < 10
    7381              :                 } // end of checking if not eql window model
    7382              :             } // end of checking if sunlitfract > 0
    7383              : 
    7384        31116 :             if (ShadeFlag == WinShadingType::SwitchableGlazing) {
    7385              :                 // Switchable glazing
    7386            0 :                 Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
    7387            0 :                 if (!s_surf->SurfWinSolarDiffusing(SurfNum)) {
    7388            0 :                     TBmBm = Window::InterpSw(SwitchFac, TBmBm, TBmAllShBlSc);
    7389              :                 } else {
    7390            0 :                     TBmDif = Window::InterpSw(SwitchFac, TBmDif, TBmAllShBlSc);
    7391              :                 }
    7392              :             }
    7393              :             // Report variables
    7394        31116 :             s_surf->SurfWinGlTsolBmBm(SurfNum) = TBmBm;
    7395        31116 :             s_surf->SurfWinGlTsolBmDif(SurfNum) = TBmDif;
    7396        31116 :             s_surf->SurfWinGlTsolDifDif(SurfNum) = TDifBare;
    7397              : 
    7398              :             //-----------------------------------------------------------------
    7399              :             // BLOCK 4 - REPORT WINDOW TRANSMITTANCE
    7400              :             //-----------------------------------------------------------------
    7401              : 
    7402              :             // The following SurfWinTransBmSolar and SurfWinTransDifSolar will be combined later to give
    7403              :             // WinTransSolar for reporting
    7404        31116 :             state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
    7405        31116 :             state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = 0.0;
    7406        31116 :             state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = 0.0;
    7407        31116 :             state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = 0.0;
    7408        31116 :             state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) =
    7409              :                 0.0; // Factor for exterior beam to beam solar transmitted through window, or window plus shade, into zone at current time (m2)
    7410        31116 :             state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) =
    7411              :                 0.0; // Factor for exterior beam to diffuse solar transmitted through window, or window plus shade, into zone at current time (m2)
    7412              : 
    7413        31116 :             Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    7414        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
    7415        29742 :                 state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
    7416        29742 :                 if (ANY_BLIND(ShadeFlag)) {
    7417            0 :                     auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    7418            0 :                     assert(matBlind != nullptr);
    7419            0 :                     if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
    7420            0 :                         state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTransGnd * surf.Area;
    7421            0 :                         state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTransSky * surf.Area;
    7422              :                     }
    7423              :                 }
    7424              :             } else {
    7425              :                 // In equivalent layer window model system diffuse transmittance is based on unit
    7426              :                 // diffuse radiation flux, and hence doesn't distinguish between sky and
    7427              :                 // ground reflected diffuse radiations
    7428         1374 :                 state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
    7429         1374 :                 state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTrans * surf.Area;
    7430         1374 :                 state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTrans * surf.Area;
    7431              :             }
    7432              : 
    7433        31116 :             if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
    7434              :                 // Unshaded or switchable glazing
    7435              :                 // Note: with previous defs of TBmBm & TBmDif, these come out right for Complex Fenestration
    7436              :                 // SurfWinTransBmSolar uses the directional-hemispherical transmittance
    7437        31116 :                 state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7438        31116 :                 state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;   // m2
    7439        31116 :                 state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
    7440              : 
    7441              :             } else {
    7442            0 :                 state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = TBmAllShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7443            0 :                 state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBmShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7444            0 :                 state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDifShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7445              :             }
    7446              : 
    7447              :             // Add diffuse transmitted by window from beam reflected from outside reveal
    7448        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
    7449            0 :                 if (FenSolAbsPtr == 0) {
    7450            0 :                     state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7451            0 :                     state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;   // m2
    7452            0 :                     state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
    7453            0 :                     state.dataSolarShading->SurfWinTransBmSolar(SurfNum) +=
    7454            0 :                         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
    7455            0 :                     state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) +=
    7456            0 :                         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
    7457              :                 } else {
    7458            0 :                     state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
    7459            0 :                     state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = 0.0;
    7460              :                 }
    7461              :             } else { // Regular window
    7462              :                 // this is also valid for equivalent layer window
    7463        31116 :                 state.dataSolarShading->SurfWinTransBmSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
    7464        31116 :                 state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
    7465              :             }
    7466              : 
    7467              :             //-----------------------------------------------------------------
    7468              :             // BLOCK 5 - UPDATE SOLAR ENTERING A ZONE AS BEAM OR DIFFUSE RADIATION
    7469              :             //-----------------------------------------------------------------
    7470              :             // Increment factor for total exterior beam solar entering zone through window as beam or diffuse
    7471        31116 :             if (SunLitFract > 0.0 && surf.Class != SurfaceClass::TDD_Dome) {
    7472              :                 // Window is schedule surface gained. Do not make addition to what enters into zone since that information is not available
    7473        16092 :                 if (FenSolAbsPtr == 0) {
    7474              :                     Real64 TBmAll; // Window beam-to-(beam+diffuse) transmittance
    7475        16092 :                     if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF && (ANY_BLIND(ShadeFlag) || ANY_SHADE_SCREEN(ShadeFlag))) {
    7476            0 :                         TBmAll = TBmAllShBlSc;
    7477              :                     } else {
    7478        16092 :                         TBmAll = TBmBm + TBmDif;
    7479              :                     }
    7480        16092 :                     BTOTZone += surf.IncSolMultiplier * TBmAll * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // [m2]
    7481              :                 }
    7482              :             }
    7483              : 
    7484              :             // Correct for effect of (1) beam absorbed by inside reveal, (2) diffuse entering zone from beam
    7485              :             // reflected by inside reveal and (3) diffuse transmitted by window from beam reflected from outside reveal.
    7486        31116 :             if (CosInc > 0.0) {
    7487              :                 // The BTOTZone is the solar into zone assuming no inside or outside reveals
    7488              :                 // The inside reveals receive solar (reflected part + absorbed part) from the window, this amount should be deducted from the
    7489              :                 // BTOTZone, then adds the InsRevealDiffIntoZone
    7490        16820 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
    7491              :                     // Do not add total into zone from scheduled surface gains.  That will be added later
    7492            0 :                     if (SurfaceScheduledSolarInc(state, SurfNum, ConstrNum) == 0) {
    7493            0 :                         BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
    7494            0 :                                    s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
    7495            0 :                                    s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
    7496              :                     }
    7497              :                 } else { // Regular window
    7498        16820 :                     BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
    7499        16820 :                                s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
    7500        16820 :                                s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
    7501              :                 }
    7502              :                 // Add beam solar absorbed by outside reveal to outside of window's base surface. Add beam solar absorbed by inside reveal to inside
    7503              :                 // of window's base surface. This ignores 2-D heat transfer effects.
    7504        16820 :                 int BaseSurfNum = surf.BaseSurf;
    7505        16820 :                 s_surf->SurfOpaqAI(BaseSurfNum) += s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
    7506        16820 :                 s_surf->SurfOpaqAO(BaseSurfNum) += s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
    7507              :             }
    7508              : 
    7509              :             //-----------------------------------------------------------------
    7510              :             // BLOCK 6 - INTERIOR BEAM FROM EXTERIOR WINDOW THAT IS ABSORBED/TRANSMITTED BY BACK SURFACES
    7511              :             //-----------------------------------------------------------------
    7512              : 
    7513              :             // If shade is in place or there is a diffusing glass layer there is no interior beam
    7514              :             // from this exterior window since the beam-beam transmittance of shades and diffusing glass
    7515              :             // is assumed to be zero. The beam-beam transmittance of tubular daylighting devices is also
    7516              :             // assumed to be zero.
    7517        31116 :             if (SunLitFract > 0.0) {
    7518        16092 :                 if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF) {
    7519        32184 :                     if (ANY_SHADE(ShadeFlag) || s_surf->SurfWinSolarDiffusing(SurfNum) || surf.OriginalClass == SurfaceClass::TDD_Diffuser ||
    7520        16092 :                         surf.Class == SurfaceClass::TDD_Dome) {
    7521            0 :                         continue;
    7522              :                     }
    7523              :                 }
    7524              : 
    7525              :                 // Find interior beam radiation that is:
    7526              :                 // (1) absorbed by opaque back surfaces;
    7527              :                 // (2) absorbed by glass layers of back surfaces that are interior or exterior windows;
    7528              :                 // (3) absorbed by interior, exterior or between-glass shades or blinds of back surfaces
    7529              :                 //       that are exterior windows; and
    7530              :                 // (4) transmitted through back surfaces that are interior or exterior windows.
    7531              :                 // Beam-beam transmittance of exterior window
    7532              :                 Real64 TBm;      // Window beam-beam transmittance
    7533              :                 Real64 TBmDenom; // TBmDenominator
    7534        16092 :                 Real64 TBmBmSc = s_surf->SurfWinScGlSysTsolBmBm(SurfNum);
    7535        16092 :                 Real64 TBmBmBl = s_surf->SurfWinBlGlSysTsolBmBm(SurfNum);
    7536        16092 :                 Real64 TBmBm = s_surf->SurfWinGlTsolBmBm(SurfNum);
    7537              : 
    7538        16092 :                 Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    7539        16092 :                 int InShelfSurf = 0; // Inside daylighting shelf surface number
    7540        16092 :                 int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
    7541        16092 :                 if (ShelfNum > 0) { // Daylighting shelf
    7542            0 :                     InShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).InSurf;
    7543              :                 }
    7544        16092 :                 if (ANY_BLIND(ShadeFlag)) {
    7545            0 :                     TBm = TBmBmBl; // Interior, exterior or between-glass blind on
    7546        16092 :                 } else if (ShadeFlag == WinShadingType::ExtScreen) {
    7547            0 :                     TBm = TBmBmSc; // Exterior screen on
    7548              :                 } else {
    7549        16092 :                     TBm = TBmBm; // Bare glass or switchable glazing
    7550              :                     // Correction for beam absorbed by inside reveal
    7551        16092 :                     TBmDenom = (SunLitFract * CosInc * surf.Area * InOutProjSLFracMult);
    7552        16092 :                     if (TBmDenom != 0.0) { // when =0.0, no correction
    7553        16081 :                         TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
    7554              :                     }
    7555        16092 :                     TBm = max(0.0, TBm);
    7556              :                     // this multiplier doesn't work with other shading, so no need to apply in other branches
    7557        16092 :                     TBm *= surf.IncSolMultiplier;
    7558              :                 }
    7559              : 
    7560        16092 :                 if (TBm == 0.0) {
    7561          309 :                     continue;
    7562              :                 }
    7563        15783 :                 if (InShelfSurf > 0) { // Inside daylighting shelf
    7564              :                     // Inside daylighting shelves assume that no beam will pass the end of the shelf.
    7565              :                     // Since all beam is absorbed on the shelf, this might cause them to get unrealistically hot at times.
    7566              :                     // BTOTWinZone - Transmitted beam solar factor for a window [m2]
    7567            0 :                     Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult;
    7568              :                     // Shelf surface area is divided by 2 because only one side sees beam (Area was multiplied by 2 during init)
    7569            0 :                     s_surf->SurfOpaqAI(InShelfSurf) += BTOTWinZone / (0.5 * s_surf->Surface(InShelfSurf).Area); //[-]
    7570            0 :                     BABSZone += BTOTWinZone;                                                                    //[m2]
    7571            0 :                     continue;
    7572            0 :                 }
    7573              : 
    7574        15783 :                 if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) { // Full interior solar distribution
    7575         2997 :                     if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
    7576              :                         // Loop over back surfaces irradiated by beam from this exterior window
    7577         8220 :                         for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
    7578              :                             int BackSurfNum =
    7579         8220 :                                 state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    7580         8220 :                             if (BackSurfNum == 0) {
    7581         2997 :                                 break; // No more irradiated back surfaces for this exterior window
    7582              :                             }
    7583              : 
    7584         5223 :                             auto &surfShadeBack = s_surf->surfShades(BackSurfNum);
    7585         5223 :                             int ConstrNumBack = s_surf->SurfActiveConstruction(BackSurfNum);
    7586         5223 :                             auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    7587              : 
    7588         5223 :                             int NBackGlass = constrBack.TotGlassLayers;
    7589              :                             // Irradiated (overlap) area for this back surface, projected onto window plane
    7590              :                             // (includes effect of shadowing on exterior window)
    7591              :                             Real64 AOverlap =
    7592         5223 :                                 state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    7593              :                             // Back surface area irradiated by beam solar from an exterior window, projected onto window plane
    7594         5223 :                             Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
    7595              :                             // AOverlap multiplied by exterior window beam transmittance and cosine of incidence angle
    7596         5223 :                             if (constrBack.TransDiff <= 0.0) {
    7597              : 
    7598              :                                 // Back surface is opaque interior or exterior wall
    7599              :                                 // Interior solar absorptance of opaque surface
    7600         5222 :                                 Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
    7601         5222 :                                 s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
    7602         5222 :                                 BABSZone += BOverlap * AbsIntSurf;                                                            //[m2]
    7603              : 
    7604              :                             } else {
    7605              : 
    7606              :                                 // Back surface is an interior or exterior window
    7607              :                                 // Note that exterior back windows can have a shading device but interior back windows
    7608              :                                 // are assumed to be bare, i.e., they have no shading device and are non-switchable.
    7609              :                                 // The layer order for interior windows is "outside" to "inside," where "outside" refers to
    7610              :                                 // the adjacent zone and "inside" refers to the current zone.
    7611            1 :                                 WinShadingType ShadeFlagBack = s_surf->SurfWinShadingFlag(BackSurfNum);
    7612            1 :                                 Real64 slatAngBack = surfShadeBack.blind.slatAng;
    7613              :                                 Real64 CosIncBack =
    7614            1 :                                     std::abs(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, BackSurfNum));
    7615            1 :                                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7616              :                                     // Transmitting window is complex fen, change the incident angle to one for ray joining
    7617              :                                     // transmitting and back window centers
    7618            0 :                                     CosIncBack = std::abs(state.dataBSDFWindow->ComplexWind(SurfNum).sdotN(IBack));
    7619              :                                 }
    7620            1 :                                 int ConstrNumBackShRaw = s_surf->SurfWinActiveShadedConstruction(BackSurfNum);
    7621            1 :                                 int const ConstrNumBackSh = ConstrNumBackShRaw == 0 ? ConstrNumBack : ConstrNumBackShRaw;
    7622            1 :                                 state.dataSolarShading->SurfWinAbsBeam.dimension(state.dataHeatBal->MaxSolidWinLayers, 0.0);
    7623            1 :                                 Real64 TransBeamWin = 0.0;           // Beam solar transmittance of a window
    7624            1 :                                 Real64 AbsBeamTotWin = 0.0;          // Sum of window glass layer beam solar absorptances
    7625            1 :                                 Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
    7626              : 
    7627              :                                 // Interior beam absorptance of glass layers and beam transmittance of back exterior  &
    7628              :                                 // or interior window WITHOUT SHADING this timestep
    7629            1 :                                 if (NOT_SHADED(ShadeFlagBack)) {
    7630            3 :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7631            2 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7632              :                                     }
    7633            1 :                                     TransBeamWin = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
    7634              :                                 }
    7635              : 
    7636              :                                 // Interior beam absorptance of glass layers and beam transmittance
    7637              :                                 // of back exterior window with SHADE
    7638            1 :                                 if (ANY_SHADE(ShadeFlagBack)) {
    7639            0 :                                     for (int Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNumBackSh).TotGlassLayers; ++Lay) {
    7640            0 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7641            0 :                                             Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
    7642              :                                     }
    7643            0 :                                     TransBeamWin = Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
    7644              :                                 }
    7645              : 
    7646              :                                 // Interior beam absorbed by INTERIOR SHADE of back exterior window
    7647            1 :                                 if (ShadeFlagBack == WinShadingType::IntShade) {
    7648            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7649            0 :                                         BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade /
    7650            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7651            0 :                                     BABSZone += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
    7652            0 :                                     backSurfBeamSolInTrans += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
    7653              : 
    7654              :                                     // Interior beam absorbed by EXTERIOR SHADE of back exterior window
    7655            1 :                                 } else if (ShadeFlagBack == WinShadingType::ExtShade) {
    7656            0 :                                     Real64 RGlFront = constrBack.ReflectSolDiffFront;
    7657            0 :                                     auto const *matSh = s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(1));
    7658            0 :                                     auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
    7659            0 :                                     assert(matFenSh != nullptr);
    7660              : 
    7661            0 :                                     Real64 AbsSh = matFenSh->AbsorpSolar;
    7662            0 :                                     Real64 RhoSh = 1.0 - AbsSh - matFenSh->Trans;
    7663            0 :                                     Real64 AShBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef) * AbsSh / (1.0 - RGlFront * RhoSh);
    7664            0 :                                     BABSZone += BOverlap * AShBack;
    7665            0 :                                     backSurfBeamSolInTrans += BOverlap * AShBack;
    7666            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7667            0 :                                         BOverlap * AShBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7668              : 
    7669              :                                     // Interior beam absorbed by BETWEEN-GLASS SHADE of back exterior window
    7670            1 :                                 } else if (ShadeFlagBack == WinShadingType::BGShade) {
    7671            0 :                                     Real64 rbd1k = constrBack.rbBareSolDiff(1);
    7672            0 :                                     Real64 rfd2k = constrBack.rfBareSolDiff(2);
    7673              :                                     Real64 AShBack; // System shade absorptance for interior beam solar
    7674            0 :                                     if (NBackGlass == 2) {
    7675            0 :                                         Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
    7676            0 :                                         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
    7677            0 :                                             s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(3)));
    7678            0 :                                         assert(matShade != nullptr);
    7679            0 :                                         Real64 TrSh = matShade->Trans;                       // Shade material solar transmittance
    7680            0 :                                         Real64 RhoSh = matShade->ReflectShade;               // Shade material solar absorptance
    7681            0 :                                         Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh)); // Shade material solar absorptance
    7682            0 :                                         AShBack = t2k * (1 + RhoSh * rfd2k + TrSh * rbd1k) * AbsSh;
    7683              :                                     } else { // NBackGlass = 3
    7684            0 :                                         Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
    7685            0 :                                         Real64 td2k = constrBack.tBareSolDiff(2);
    7686            0 :                                         Real64 rbd2k = constrBack.rbBareSolDiff(2);
    7687            0 :                                         Real64 rfd3k = constrBack.rfBareSolDiff(3);
    7688            0 :                                         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
    7689            0 :                                             s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(5)));
    7690            0 :                                         assert(matShade != nullptr);
    7691            0 :                                         Real64 TrSh = matShade->Trans;
    7692            0 :                                         Real64 RhoSh = matShade->ReflectShade;
    7693            0 :                                         Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh));
    7694            0 :                                         AShBack = t3k * (1 + RhoSh * rfd3k + TrSh * (rbd2k + td2k * rbd1k * td2k)) * AbsSh;
    7695              :                                     }
    7696            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7697            0 :                                         BOverlap * AShBack / s_surf->Surface(BackSurfNum).Area;
    7698            0 :                                     BABSZone += BOverlap * AShBack;
    7699            0 :                                     backSurfBeamSolInTrans += BOverlap * AShBack;
    7700              :                                 }
    7701              : 
    7702              :                                 // Interior beam absorptance of glass layers and beam absorbed in blind
    7703              :                                 // of back exterior window with BLIND
    7704            1 :                                 if (ANY_BLIND(ShadeFlagBack)) {
    7705            0 :                                     auto const &btarBack = surfShadeBack.blind.TAR;
    7706              :                                     auto const *matBlindBack =
    7707            0 :                                         dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShadeBack.blind.matNum));
    7708            0 :                                     assert(matBlindBack != nullptr);
    7709              : 
    7710            0 :                                     auto const &btar = surfShade.blind.TAR;
    7711            0 :                                     Real64 profAngBack = surfShadeBack.blind.profAng;
    7712              : 
    7713            0 :                                     int profIdxLoBack = surfShadeBack.blind.profAngIdxLo;
    7714            0 :                                     int profIdxHiBack = surfShadeBack.blind.profAngIdxHi;
    7715            0 :                                     Real64 profInterpFacBack = surfShadeBack.blind.profAngInterpFac;
    7716              : 
    7717            0 :                                     Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
    7718            0 :                                     Real64 TBlBmBmBack = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
    7719              : 
    7720              :                                     // Blind solar back beam-diffuse transmittance
    7721              :                                     // Is this supposed to be blindBack?
    7722              :                                     Real64 TBlBmDiffBack =
    7723            0 :                                         Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxLoBack].DfTra, profInterpFacBack);
    7724              : 
    7725            0 :                                     if (ShadeFlagBack == WinShadingType::IntBlind) {
    7726              :                                         // Interior beam absorptance of GLASS LAYERS of exterior back window with INTERIOR BLIND
    7727            0 :                                         FrontDiffDiffRefl = btarBack.Sol.Ft.Df.Ref; // Blind solar front beam reflectance
    7728            0 :                                         FrontDiffAbs = btarBack.Sol.Ft.Df.Abs;
    7729              :                                         Real64 RhoBlFront =
    7730            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7731              :                                         Real64 AbsBlFront =
    7732            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7733              :                                         Real64 AbsBlBack =
    7734            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7735              : 
    7736            0 :                                         Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Glazing system solar back beam-beam reflectance
    7737            0 :                                         Real64 RGlBack = Window::POLYF(
    7738            0 :                                             CosIncBack, constrBack.ReflSolBeamBackCoef); // Glazing system back diffuse solar reflectance
    7739            0 :                                         Real64 RGlDiffBack = constrBack.ReflectSolDiffBack;
    7740            0 :                                         for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7741            0 :                                             Real64 AbWinBack = Window::POLYF(
    7742              :                                                 CosIncBack,
    7743              :                                                 constrBack.AbsBeamBackCoef(Lay)); // Factor for back beam radiation absorbed in window glass layer
    7744            0 :                                             Real64 AGlDiffBack = constrBack.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
    7745            0 :                                             state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7746            0 :                                                 TBlBmBmBack * AbWinBack + ((TBlBmBmBack * RGlBack * RhoBlFront + TBlBmDiffBack) * AGlDiffBack /
    7747            0 :                                                                            (1.0 - RGlDiffBack * RhoBlDiffFront));
    7748              :                                         }
    7749              : 
    7750              :                                         // Interior beam transmitted by exterior back window with INTERIOR BLIND
    7751            0 :                                         Real64 TGlDif = constrBack.TransDiff; // Bare diffuse transmittance of back window
    7752            0 :                                         TransBeamWin =
    7753            0 :                                             TBlBmBmBack * (TGlBmBack + TGlDif * RGlBack * RhoBlFront / (1.0 - RGlDiffBack * RhoBlDiffFront)) +
    7754            0 :                                             TBlBmDiffBack * TGlDif / (1.0 - RGlDiffBack * RhoBlDiffFront);
    7755              : 
    7756              :                                         // Interior beam absorbed by BLIND on exterior back window with INTERIOR BLIND
    7757              : 
    7758            0 :                                         Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
    7759            0 :                                         Real64 ABlBack = AbsBlBack + TBlBmBmBack * RGlBack * AbsBlFront +
    7760            0 :                                                          (AbsBlDiffFront * RGlDiffBack / (1 - RhoBlDiffFront * RGlDiffBack)) *
    7761            0 :                                                              (RGlBack * TBlBmBmBack * RhoBlFront +
    7762              :                                                               TBlBmDiffBack); // Blind solar back absorptance for interior solar
    7763            0 :                                         state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7764            0 :                                             BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7765            0 :                                         BABSZone += BOverlap * ABlBack;
    7766            0 :                                         backSurfBeamSolInTrans += BOverlap * ABlBack;
    7767              : 
    7768            0 :                                     } else if (ShadeFlagBack == WinShadingType::ExtBlind) {
    7769              : 
    7770              :                                         // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR BLIND
    7771              : 
    7772            0 :                                         Real64 RGlDiffFront = state.dataConstruction->Construct(ConstrNumBack)
    7773            0 :                                                                   .ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
    7774              : 
    7775              :                                         // Is this supposed to be beam-beam reflection?
    7776              :                                         Real64 RhoBlBack =
    7777            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7778              :                                         Real64 RhoBlBmDifBk =
    7779            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7780              :                                         Real64 AbsBlBack =
    7781            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7782              : 
    7783            0 :                                         for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7784            0 :                                             Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7785            0 :                                             Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
    7786            0 :                                             state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7787            0 :                                                 AbWinBack + (TGlBmBack * AGlDiffFront * RhoBlBack / (1.0 - RhoBlBack * RGlDiffFront));
    7788              :                                         }
    7789              : 
    7790              :                                         // Interior beam transmitted by exterior back window with EXTERIOR BLIND
    7791            0 :                                         Real64 TBlDifDif = BackDiffDiffTrans;
    7792            0 :                                         Real64 RhoBlDifDifBk = BackDiffDiffRefl;
    7793            0 :                                         Real64 AbsBlDiffBack = BackDiffAbs;
    7794            0 :                                         Real64 ABlBack =
    7795            0 :                                             TGlBmBack * (AbsBlBack + RhoBlBack * RGlDiffFront * AbsBlDiffBack / (1 - RhoBlDifDifBk * RGlDiffFront));
    7796            0 :                                         Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7797            0 :                                         TransBeamWin = TGlBmBack * (TBlBmBmBack + TBlBmDiffBack +
    7798            0 :                                                                     TBlDifDif * RhoBlBmDifBk * RGlDifFr / (1.0 - RhoBlDifDifBk * RGlDifFr));
    7799              :                                         // Interior beam absorbed by EXTERIOR BLIND on exterior back window
    7800            0 :                                         BABSZone += BOverlap * ABlBack;
    7801            0 :                                         backSurfBeamSolInTrans += BOverlap * ABlBack;
    7802            0 :                                         state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7803            0 :                                             BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7804              : 
    7805              :                                     } else {
    7806              :                                         // ShadeFlagBack == BGBlindOn
    7807            0 :                                         Real64 t1k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(1));
    7808            0 :                                         Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
    7809            0 :                                         Real64 af2k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(2));
    7810            0 :                                         Real64 ab1k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(1));
    7811            0 :                                         Real64 ab2k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(2));
    7812            0 :                                         Real64 rb1k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(1));
    7813            0 :                                         Real64 rb2k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(2));
    7814            0 :                                         Real64 td1k = constrBack.tBareSolDiff(1);
    7815            0 :                                         Real64 td2k = constrBack.tBareSolDiff(2);
    7816            0 :                                         Real64 afd2k = constrBack.afBareSolDiff(2);
    7817            0 :                                         Real64 abd1k = constrBack.abBareSolDiff(1);
    7818            0 :                                         Real64 abd2k = constrBack.abBareSolDiff(2);
    7819            0 :                                         Real64 rfd2k = constrBack.rfBareSolDiff(2);
    7820            0 :                                         Real64 rbd1k = constrBack.rbBareSolDiff(1);
    7821            0 :                                         Real64 rbd2k = constrBack.rbBareSolDiff(2);
    7822            0 :                                         Real64 tfshBBk = matBlindBack->BeamBeamTrans(profAngBack, slatAngBack);
    7823            0 :                                         Real64 tbshBBk = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
    7824              : 
    7825              :                                         Real64 tfshBdk =
    7826            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfTra, btar.Sol.Ft.Bm[profIdxHiBack].DfTra, profInterpFacBack);
    7827              :                                         Real64 tbshBdk =
    7828            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxHiBack].DfTra, profInterpFacBack);
    7829              :                                         Real64 rfshBk =
    7830            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7831              :                                         Real64 rbshBk =
    7832            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7833              :                                         Real64 afshBk =
    7834            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7835              :                                         Real64 abshBk =
    7836            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7837            0 :                                         Real64 tfshdk = btarBack.Sol.Ft.Df.Tra;
    7838            0 :                                         Real64 rfshdk = btarBack.Sol.Ft.Df.Ref;
    7839            0 :                                         Real64 afshdk = btarBack.Sol.Ft.Df.Abs;
    7840            0 :                                         Real64 tbshdk = btarBack.Sol.Bk.Df.Tra;
    7841            0 :                                         Real64 rbshdk = btarBack.Sol.Bk.Df.Ref;
    7842            0 :                                         Real64 abshdk = btarBack.Sol.Bk.Df.Abs;
    7843              :                                         Real64 ABlBack;
    7844              : 
    7845            0 :                                         if (NBackGlass == 2) {
    7846              :                                             // Interior beam absorptance of GLASS LAYERS of exterior back window with BETWEEN-GLASS BLIND
    7847            0 :                                             state.dataSolarShading->SurfWinAbsBeam(2) =
    7848            0 :                                                 ab2k + t2k * tbshBBk * rb1k * tfshBBk * af2k +
    7849            0 :                                                 t2k * (tbshBBk * rb1k * tfshBdk + tbshBdk * rbd1k * tfshdk + rbshBk * (1.0 + rfd2k * rbshdk)) * afd2k;
    7850            0 :                                             state.dataSolarShading->SurfWinAbsBeam(1) =
    7851            0 :                                                 t2k * tbshBBk * ab1k + t2k * (rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * abd1k;
    7852              :                                             // Interior beam transmitted by exterior back window with BETWEEN-GLASS BLIND
    7853            0 :                                             TransBeamWin =
    7854            0 :                                                 t2k * tbshBBk * t1k +
    7855            0 :                                                 t2k * (tbshBBk * rb1k * rfshBk + rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * td1k;
    7856              :                                             // Interior beam absorbed by BLIND on exterior back window with BETWEEN-GLASS BLIND
    7857            0 :                                             ABlBack = t2k * (abshBk + tbshBBk * rb1k * afshBk + rbshBk * rfd2k * abshdk + tbshBdk * rbd1k * afshdk);
    7858              :                                         } else { // NBackGlass = 3
    7859            0 :                                             Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
    7860            0 :                                             Real64 af3k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(3));
    7861            0 :                                             Real64 ab3k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(3));
    7862            0 :                                             Real64 afd3k = constrBack.afBareSolDiff(3);
    7863            0 :                                             Real64 rfd3k = constrBack.rfBareSolDiff(3);
    7864            0 :                                             state.dataSolarShading->SurfWinAbsBeam(3) =
    7865            0 :                                                 ab3k + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * tfshBBk * af3k +
    7866            0 :                                                 t3k *
    7867            0 :                                                     (tbshBdk * rbd2k * tfshdk + tbshBdk * td2k * rbd1k * td2k * tfshdk +
    7868            0 :                                                      rbshBk * (1.0 + rfd3k * rbshdk)) *
    7869              :                                                     afd3k;
    7870            0 :                                             state.dataSolarShading->SurfWinAbsBeam(2) =
    7871            0 :                                                 t3k * tbshBBk * (ab2k + t2k * rb1k * (af2k + t2k * rfshBk * abd2k)) +
    7872            0 :                                                 t3k * (tbshBdk + tbshBdk * (rbd2k + td2k * rbd1k * td2k) * rfshdk + rbshBk * rfd3k * tbshdk) * abd2k +
    7873            0 :                                                 t3k * tbshBdk * td2k * rbd1k * afd2k;
    7874            0 :                                             state.dataSolarShading->SurfWinAbsBeam(1) =
    7875            0 :                                                 t3k * tbshBBk * (t2k * ab1k + (rb2k + t2k * rb1k * t2k) * rfshBk * td2k * abd1k) +
    7876            0 :                                                 t3k * (rbshBk * rfd3k * tbshdk + tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd2k * td2k * rfshdk)) *
    7877            0 :                                                     td2k * abd1k;
    7878            0 :                                             TransBeamWin = t3k * tbshBBk * t2k * t1k +
    7879            0 :                                                            t3k *
    7880            0 :                                                                (tbshBBk * (rb2k * rfshBk + t2k * rb1k * t2k * rfshBk) + rbshBk * rfd3k * tbshdk +
    7881            0 :                                                                 tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd1k * td2k * rfshdk)) *
    7882            0 :                                                                td2k * td1k;
    7883            0 :                                             ABlBack = t3k * abshBk + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * afshBk +
    7884            0 :                                                       t3k * rbshBk * rfd3k * abshdk + t3k * tbshBdk * (rbd2k + td2k * rbd1k * td2k) * afshdk;
    7885              :                                         }
    7886              : 
    7887            0 :                                         BABSZone += BOverlap * ABlBack;
    7888            0 :                                         backSurfBeamSolInTrans += BOverlap * ABlBack;
    7889            0 :                                         state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7890            0 :                                             BOverlap * ABlBack / s_surf->Surface(BackSurfNum).Area;
    7891              : 
    7892              :                                     } // End of check if between-glass blind is on back window
    7893            1 :                                 } else if (ShadeFlagBack == WinShadingType::ExtScreen) {
    7894              : 
    7895              :                                     // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR SCREEN
    7896            0 :                                     Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
    7897            0 :                                     Real64 RGlDiffFront = constrBack.ReflectSolDiffFront;
    7898              : 
    7899            0 :                                     auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    7900            0 :                                     assert(screen != nullptr);
    7901              : 
    7902            0 :                                     auto &surf = s_surf->Surface(SurfNum);
    7903            0 :                                     Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
    7904            0 :                                     Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
    7905            0 :                                     Real64 winPhi = surf.Tilt * Constant::DegToRad;
    7906            0 :                                     Real64 winTheta = surf.Azimuth * Constant::DegToRad;
    7907            0 :                                     Real64 phi = std::abs(solPhi - winPhi);
    7908            0 :                                     Real64 theta = std::abs(solTheta - winTheta);
    7909            0 :                                     Material::NormalizePhiTheta(phi, theta);
    7910              : #ifdef PRECALC_INTERP_SCREEN
    7911              :                                     int ip1, ip2, it1, it2;
    7912              :                                     BilinearInterpCoeffs coeffs;
    7913            0 :                                     Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
    7914            0 :                                     GetBilinearInterpCoeffs(
    7915            0 :                                         phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
    7916            0 :                                     auto const &b11 = screen->btars[ip1][it1];
    7917            0 :                                     auto const &b12 = screen->btars[ip1][it2];
    7918            0 :                                     auto const &b21 = screen->btars[ip2][it1];
    7919            0 :                                     auto const &b22 = screen->btars[ip2][it2];
    7920              : 
    7921            0 :                                     Real64 TScBmBmBack = BilinearInterp(b11.BmTransBack, b12.BmTransBack, b21.BmTransBack, b22.BmTransBack, coeffs);
    7922            0 :                                     Real64 TScBmDiffBack = BilinearInterp(b11.DfTransBack, b12.DfTransBack, b21.DfTransBack, b22.DfTransBack, coeffs);
    7923            0 :                                     Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    7924            0 :                                     Real64 RScDifBack = screen->DfRef;
    7925            0 :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7926            0 :                                         Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7927            0 :                                         Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
    7928            0 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7929            0 :                                             AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
    7930              :                                     }
    7931              : 
    7932              :                                     // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
    7933            0 :                                     Real64 TScDifDif = screen->DfTrans;
    7934            0 :                                     Real64 RScBmDifBk = BilinearInterp(b11.RefSolBack, b12.RefSolBack, b21.RefSolBack, b22.RefSolBack, coeffs);
    7935            0 :                                     Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7936            0 :                                     Real64 RScDifDifBk = screen->DfRef;
    7937            0 :                                     TransBeamWin = TGlBmBack *
    7938            0 :                                                    (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
    7939              : 
    7940              :                                     // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
    7941            0 :                                     Real64 AbsScBack = BilinearInterp(b11.AbsSolBack, b12.AbsSolBack, b21.AbsSolBack, b22.AbsSolBack, coeffs);
    7942            0 :                                     Real64 AbsScDiffBack = screen->DfAbs;
    7943            0 :                                     Real64 RScDiffBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    7944              :                                     // Screen solar back absorptance for interior solar
    7945            0 :                                     Real64 AScBack =
    7946            0 :                                         TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
    7947              : 
    7948            0 :                                     BABSZone += BOverlap * AScBack;
    7949            0 :                                     backSurfBeamSolInTrans += BOverlap * AScBack;
    7950            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7951            0 :                                         BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7952              : #else  // !PRECALC_INTERP_SCREEN
    7953              :                                     Material::ScreenBmTransAbsRef btar;
    7954              :                                     Material::CalcScreenTransmittance(state, screen, phi, theta, btar);
    7955              : 
    7956              :                                     Real64 TScBmBmBack = btar.BmTransBack;
    7957              :                                     Real64 TScBmDiffBack = btar.DfTransBack;
    7958              :                                     Real64 RScBack = btar.RefSolFront;
    7959              :                                     Real64 RScDifBack = screen->DfRef;
    7960              :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7961              :                                         Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7962              :                                         Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
    7963              :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7964              :                                             AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
    7965              :                                     }
    7966              : 
    7967              :                                     // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
    7968              :                                     Real64 TScDifDif = screen->DfTrans;
    7969              :                                     Real64 RScBmDifBk = btar.RefSolBack;
    7970              :                                     Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7971              :                                     Real64 RScDifDifBk = screen->DfRef;
    7972              :                                     TransBeamWin = TGlBmBack *
    7973              :                                                    (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
    7974              : 
    7975              :                                     // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
    7976              :                                     Real64 AbsScBack = btar.AbsSolBack;
    7977              :                                     Real64 AbsScDiffBack = screen->DfAbs;
    7978              :                                     Real64 RScDiffBack = btar.RefSolFront;
    7979              :                                     // Screen solar back absorptance for interior solar
    7980              :                                     Real64 AScBack =
    7981              :                                         TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
    7982              : 
    7983              :                                     BABSZone += BOverlap * AScBack;
    7984              :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7985              :                                         BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7986              : #endif // PRECALC_INTERP_SCREEN
    7987              : 
    7988              :                                 } // End of check if exterior screen on back window
    7989              : 
    7990              :                                 // Interior beam absorptance of glass layers of back exterior window with SWITCHABLE GLAZING
    7991            1 :                                 if (ShadeFlagBack == WinShadingType::SwitchableGlazing && s_surf->Surface(BackSurfNum).ExtBoundCond == 0) {
    7992            0 :                                     Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
    7993              :                                     Real64 AbsBeamWinSh; // Glass layer beam solar absorptance of a shaded window
    7994            0 :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7995              :                                         AbsBeamWinSh =
    7996            0 :                                             Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
    7997            0 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7998            0 :                                             Window::InterpSw(SwitchFac, state.dataSolarShading->SurfWinAbsBeam(Lay), AbsBeamWinSh);
    7999              :                                     }
    8000              :                                     // Beam solar transmittance of a shaded window
    8001              :                                     Real64 TransBeamWinSh =
    8002            0 :                                         Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
    8003            0 :                                     TransBeamWin = Window::InterpSw(SwitchFac, TransBeamWin, TransBeamWinSh);
    8004              :                                 }
    8005              : 
    8006              :                                 // Sum of interior beam absorbed by all glass layers of back window
    8007            1 :                                 AbsBeamTotWin = 0.0;
    8008            3 :                                 for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    8009            2 :                                     AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeam(Lay);
    8010            2 :                                     s_surf->SurfWinA(BackSurfNum, Lay) +=
    8011            2 :                                         BOverlap * state.dataSolarShading->SurfWinAbsBeam(Lay) /
    8012            2 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
    8013              :                                 }
    8014              : 
    8015              :                                 // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
    8016            1 :                                 BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
    8017            1 :                                 backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
    8018            1 :                                 state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
    8019            1 :                                     backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
    8020              :                                 // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
    8021              :                                 // this beam radiation is categorized as diffuse radiation in the adjacent zone.
    8022            1 :                                 int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
    8023            1 :                                 if (AdjSurfNum > 0) {
    8024            0 :                                     int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    8025            0 :                                     state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
    8026            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
    8027            0 :                                         BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
    8028            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
    8029            0 :                                         s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    8030              :                                 }
    8031              :                             } // End of check if back surface is opaque or window
    8032         5223 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
    8033         5223 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
    8034         5223 :                                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    8035              :                         } // End of loop over back surfaces
    8036            0 :                     } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    8037              :                         // For complex window calculation goes over outgoing basis directions for current state
    8038            0 :                         int CurCplxFenState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState; // Current state for complex fenestration
    8039              :                         // Get construction number which keeps transmittance properties
    8040            0 :                         int IConst = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurCplxFenState).Konst; // Current surface construction number
    8041              :                                                                                                              // (it depends of state too)
    8042              :                         // Solar radiation from this window will be calculated only in case when this window is not scheduled surface gained
    8043            0 :                         if (WindowScheduledSolarAbs(state, SurfNum, IConst) == 0) {
    8044              :                             // Current incoming direction number (Sun direction)
    8045            0 :                             int IBm = state.dataBSDFWindow->ComplexWind(SurfNum)
    8046            0 :                                           .Geom(CurCplxFenState)
    8047            0 :                                           .SolBmIndex(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    8048              :                             // Report variables for complex fenestration here
    8049            0 :                             state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfNum) = IBm;
    8050            0 :                             state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfNum) =
    8051            0 :                                 state.dataBSDFWindow->ComplexWind(SurfNum)
    8052            0 :                                     .Geom(CurCplxFenState)
    8053            0 :                                     .ThetaBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    8054            0 :                             state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfNum) = state.dataBSDFWindow->ComplexWind(SurfNum)
    8055            0 :                                                                                     .Geom(CurCplxFenState)
    8056            0 :                                                                                     .PhiBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    8057              : 
    8058            0 :                             int BaseSurf = surf.BaseSurf; // Base surface number for current complex window
    8059              :                             // Get total number of back surfaces for current window (surface)
    8060              :                             // Note that it is organized by base surface
    8061            0 :                             int NBkSurf = state.dataShadowComb->ShadowComb(BaseSurf).NumBackSurf;
    8062            0 :                             if (!allocated(CFBoverlap)) {
    8063            0 :                                 CFBoverlap.allocate(NBkSurf);
    8064              :                             }
    8065            0 :                             if (!allocated(CFDirBoverlap)) {
    8066            0 :                                 CFDirBoverlap.allocate(NBkSurf, state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis);
    8067              :                             }
    8068              : 
    8069            0 :                             CFBoverlap = 0.0;
    8070              :                             // Calculate effects on all back surfaces for each of basis directions.  Each of basis directions from the back of the
    8071              :                             // window has to be considered as beam and therefore calculate CFBoverlap for each of them
    8072            0 :                             for (int CurTrnDir = 1; CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
    8073              :                                  ++CurTrnDir) {
    8074            0 :                                 Real64 CurLambda = state.dataBSDFWindow->ComplexWind(SurfNum)
    8075            0 :                                                        .Geom(CurCplxFenState)
    8076            0 :                                                        .Trn.Lamda(CurTrnDir); // Current lambda value in BSDF outgoing directions
    8077            0 :                                 Real64 DirTrans = state.dataConstruction->Construct(IConst).BSDFInput.SolFrtTrans(
    8078            0 :                                     IBm, CurTrnDir); // Current BSDF directional transmittance
    8079              :                                 // Now calculate effect of this direction on all back surfaces
    8080            0 :                                 for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
    8081            0 :                                     CFDirBoverlap(IBack, CurTrnDir) =
    8082            0 :                                         state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).AOverlap(IBack, CurTrnDir) * DirTrans *
    8083            0 :                                         CurLambda * CosInc;
    8084            0 :                                     CFBoverlap(IBack) += CFDirBoverlap(IBack, CurTrnDir);
    8085              :                                 } // DO IBack = 1,MaxBkSurf
    8086              :                             }
    8087              : 
    8088              :                             // Summarizing results
    8089            0 :                             for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
    8090            0 :                                 int BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(IBack);
    8091            0 :                                 int ConstrNumBack = s_surf->Surface(BackSurfaceNumber).Construction;
    8092            0 :                                 auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    8093              :                                 // Do not perform any calculation if surface is scheduled for incoming solar radiation
    8094            0 :                                 int SurfSolIncPtr = SurfaceScheduledSolarInc(state, BackSurfaceNumber, ConstrNumBack);
    8095              : 
    8096            0 :                                 if (SurfSolIncPtr == 0) {
    8097              :                                     // Surface hit is another complex fenestration
    8098            0 :                                     if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
    8099              :                                         int CurBackState =
    8100            0 :                                             s_surf->SurfaceWindow(BackSurfaceNumber)
    8101            0 :                                                 .ComplexFen.CurrentState; // Current state for back surface if that surface is complex fenestration
    8102              :                                         // Do not take into account this window if it is scheduled for surface gains
    8103            0 :                                         if (WindowScheduledSolarAbs(state, BackSurfaceNumber, ConstrNumBack) == 0) {
    8104              :                                             // Calculate energy loss per each outgoing orientation
    8105            0 :                                             for (int CurTrnDir = 1;
    8106            0 :                                                  CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
    8107              :                                                  ++CurTrnDir) {
    8108              :                                                 Real64 bestDot; // complex fenestration hits other complex fenestration, it is important to find
    8109              :                                                 // matching beam directions.  Beam leaving one window will have certain number for it's basis
    8110              :                                                 // while same beam reaching back surface will have different beam number.  This value is used
    8111              :                                                 // to keep best matching dot product for those directions
    8112              :                                                 Real64 curDot;   // temporary variable for current dot product
    8113              :                                                 int bestBackTrn; // Direction corresponding best dot product for back surface window
    8114            0 :                                                 for (int CurBackDir = 1;
    8115            0 :                                                      CurBackDir <= state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).Trn.NBasis;
    8116              :                                                      ++CurBackDir) {
    8117              :                                                     // Purpose of this part is to find best match for outgoing beam number of window back surface
    8118              :                                                     // and incoming beam number of complex fenestration which this beam will hit on (back surface
    8119              :                                                     // again)
    8120              :                                                     curDot =
    8121            0 :                                                         dot(state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).sTrn(CurTrnDir),
    8122            0 :                                                             state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).sTrn(CurBackDir));
    8123            0 :                                                     if (CurBackDir == 1) {
    8124            0 :                                                         bestDot = curDot;
    8125            0 :                                                         bestBackTrn = CurBackDir;
    8126              :                                                     } else {
    8127            0 :                                                         if (curDot < bestDot) {
    8128            0 :                                                             bestDot = curDot;
    8129            0 :                                                             bestBackTrn = CurBackDir;
    8130              :                                                         }
    8131              :                                                     }
    8132              :                                                 }
    8133              :                                                 // CurLambda = ComplexWind(BackSurfaceNumber)%Geom(CurBackState)%Trn%Lamda(CurTrnDir)
    8134              :                                                 // Add influence of this exact direction to what stays in the zone.  It is important to note that
    8135              :                                                 // this needs to be done for each outgoing direction
    8136            0 :                                                 Real64 babs = CFDirBoverlap(IBack, CurTrnDir) * (1 - s_surf->SurfaceWindow(BackSurfaceNumber)
    8137            0 :                                                                                                          .ComplexFen.State(CurBackState)
    8138            0 :                                                                                                          .IntegratedBkRefl(bestBackTrn));
    8139            0 :                                                 BABSZone += babs;
    8140            0 :                                                 state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfaceNumber) +=
    8141            0 :                                                     babs * state.dataEnvrn->BeamSolarRad; //[W]
    8142              : 
    8143              :                                                 // Absorptance from current back direction
    8144            0 :                                                 int TotSolidLay = constrBack.TotSolidLayers;
    8145            0 :                                                 for (int Lay = 1; Lay <= TotSolidLay; ++Lay) {
    8146              :                                                     // IF (ALLOCATED(Construct(ConstrNumBack)%BSDFInput)) THEN
    8147              :                                                     // CFDirBoverlap is energy transmitted for current basis beam.  It is important to note that
    8148              :                                                     // AWinOverlap array needs to contain flux and not absorbed energy because later in the code
    8149              :                                                     // this will be multiplied with window area
    8150            0 :                                                     s_surf->SurfWinACFOverlap(BackSurfaceNumber, Lay) +=
    8151            0 :                                                         constrBack.BSDFInput.Layer(Lay).BkAbs(bestBackTrn, 1) * CFDirBoverlap(IBack, CurTrnDir) /
    8152            0 :                                                         s_surf->Surface(BackSurfaceNumber).Area;
    8153              :                                                     // END IF
    8154              :                                                 }
    8155              : 
    8156              :                                                 // Interior beam transmitted to adjacent zone through an interior back window;
    8157              :                                                 // This beam radiation is categorized as diffuse radiation in the adjacent zone.
    8158              :                                                 // Note that this is done for each outgoing direction of exterior window
    8159            0 :                                                 int AdjSurfNum = s_surf->Surface(BackSurfaceNumber).ExtBoundCond;
    8160            0 :                                                 if (AdjSurfNum > 0) {
    8161            0 :                                                     int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    8162            0 :                                                     state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) +=
    8163            0 :                                                         CFDirBoverlap(IBack, CurTrnDir) * s_surf->SurfaceWindow(BackSurfaceNumber)
    8164            0 :                                                                                               .ComplexFen.State(CurBackState)
    8165            0 :                                                                                               .IntegratedBkTrans(bestBackTrn);
    8166            0 :                                                     s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) +=
    8167            0 :                                                         CFDirBoverlap(IBack, CurTrnDir) *
    8168            0 :                                                         s_surf->SurfaceWindow(BackSurfaceNumber)
    8169            0 :                                                             .ComplexFen.State(CurBackState)
    8170            0 :                                                             .IntegratedBkTrans(bestBackTrn) *
    8171            0 :                                                         state.dataEnvrn->BeamSolarRad; //[W]
    8172            0 :                                                     s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfaceNumber) =
    8173            0 :                                                         s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) * state.dataGlobal->TimeStepZoneSec;
    8174              :                                                 }
    8175              :                                             }
    8176              :                                         }
    8177              :                                     } else {
    8178            0 :                                         if (constrBack.TransDiff <= 0.0) {
    8179              :                                             // Do not take into account this window if it is scheduled for surface gains
    8180            0 :                                             Real64 AbsIntSurf = constrBack.InsideAbsorpSolar;
    8181            0 :                                             s_surf->SurfOpaqAI(BackSurfaceNumber) +=
    8182            0 :                                                 CFBoverlap(IBack) * AbsIntSurf / s_surf->Surface(BackSurfaceNumber).Area;
    8183            0 :                                             BABSZone += CFBoverlap(IBack) * AbsIntSurf;
    8184              :                                         } else {
    8185              :                                             // Code for mixed windows goes here.  It is same as above code for "ordinary" windows.
    8186              :                                             // Try to do something which will not produce duplicate code.
    8187              :                                         }
    8188              :                                     }
    8189              :                                 }
    8190              :                             }
    8191              : 
    8192            0 :                             if (allocated(CFBoverlap)) {
    8193            0 :                                 CFBoverlap.deallocate();
    8194              :                             }
    8195            0 :                             if (allocated(CFDirBoverlap)) {
    8196            0 :                                 CFDirBoverlap.deallocate();
    8197              :                             }
    8198              :                         }
    8199              : 
    8200            0 :                     } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
    8201              : 
    8202            0 :                         for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
    8203              :                             int BackSurfNum =
    8204            0 :                                 state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8205            0 :                             if (BackSurfNum == 0) {
    8206            0 :                                 break; // No more irradiated back surfaces for this exterior window
    8207              :                             }
    8208            0 :                             if (s_surf->SurfWinWindowModelType(IBack) != WindowModel::EQL) {
    8209            0 :                                 continue; // only EQL back window is allowed
    8210              :                             }
    8211              : 
    8212            0 :                             int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
    8213            0 :                             auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    8214            0 :                             int NBackGlass = constrBack.TotGlassLayers;
    8215              :                             // Irradiated (overlap) area for this back surface, projected onto window plane
    8216              :                             // (includes effect of shadowing on exterior window)
    8217              : 
    8218              :                             Real64 AOverlap =
    8219            0 :                                 state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8220            0 :                             Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
    8221              : 
    8222            0 :                             if (constrBack.TransDiff <= 0.0) {
    8223              : 
    8224              :                                 // Back surface is opaque interior or exterior wall
    8225            0 :                                 Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
    8226            0 :                                 s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
    8227            0 :                                 BABSZone += BOverlap * AbsIntSurf;                                                            //[m2]
    8228              : 
    8229              :                             } else {
    8230              : 
    8231              :                                 // Back surface is an interior or exterior window
    8232              :                                 // Note that exterior back windows with and without shades are treated as defined.
    8233              :                                 // Equivalent Layer window model has no distinction when treating windows with and
    8234              :                                 // without shades (interior, inbetween and exterior shades)
    8235              :                                 //  Note in equivalent layer window model if storm window exists it is defined as part of
    8236              :                                 //  window construction, hence it does not require a separate treatment
    8237            0 :                                 state.dataSolarShading->SurfWinAbsBeamEQL = 0.0;
    8238            0 :                                 Real64 TransBeamWin = 0.0;           // Beam solar transmittance of a window
    8239            0 :                                 Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
    8240              : 
    8241              :                                 // Interior beam absorptance of glass layers and beam transmittance of back exterior  &
    8242              :                                 // or interior window (treats windows with/without shades as defined) for this timestep
    8243              : 
    8244              :                                 // call the ASHWAT fenestration model for beam radiation here
    8245            0 :                                 WindowEquivalentLayer::CalcEQLOpticalProperty(
    8246            0 :                                     state, BackSurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamBackEQL);
    8247            0 :                                 auto &CFS = state.dataWindowEquivLayer->CFS;
    8248            0 :                                 int EQLNum = constrBack.EQLConsPtr;
    8249            0 :                                 state.dataSolarShading->SurfWinAbsBeamEQL({1, CFS(EQLNum).NL}) =
    8250            0 :                                     state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, {1, CFS(EQLNum).NL});
    8251              :                                 // get the interior beam transmitted through back exterior or interior EQL window
    8252            0 :                                 TransBeamWin = state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL + 1);
    8253              :                                 //   Absorbed by the interior shade layer of back exterior window
    8254            0 :                                 if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
    8255            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    8256            0 :                                         BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL) /
    8257            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    8258            0 :                                     BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
    8259            0 :                                     backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
    8260              :                                 }
    8261              :                                 //   Absorbed by the exterior shade layer of back exterior window
    8262            0 :                                 if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
    8263            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    8264            0 :                                         BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1) /
    8265            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    8266            0 :                                     BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
    8267            0 :                                     backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
    8268              :                                 }
    8269              : 
    8270              :                                 // determine the number of glass layers
    8271            0 :                                 NBackGlass = 0;
    8272            0 :                                 for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
    8273            0 :                                     if (CFS(EQLNum).L(Lay).LTYPE != LayerType::GLAZE) {
    8274            0 :                                         continue;
    8275              :                                     }
    8276            0 :                                     ++NBackGlass;
    8277              :                                 }
    8278            0 :                                 if (NBackGlass >= 2) {
    8279              :                                     // If the number of glass is greater than 2, in between glass shade can be present
    8280            0 :                                     for (int Lay = 2; Lay <= CFS(EQLNum).NL - 1; ++Lay) {
    8281            0 :                                         if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
    8282              :                                             // if there is in between shade glass determine the shade absorptance
    8283            0 :                                             state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) +=
    8284            0 :                                                 BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay) /
    8285            0 :                                                 s_surf->Surface(BackSurfNum).Area;
    8286            0 :                                             BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
    8287            0 :                                             backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
    8288              :                                         }
    8289              :                                     }
    8290              :                                 }
    8291              :                                 // Sum of interior beam absorbed by all glass layers of back window
    8292            0 :                                 Real64 AbsBeamTotWin = 0.0; // Glass layer beam solar absorptance of a shaded window
    8293            0 :                                 for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
    8294            0 :                                     AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeamEQL(Lay);
    8295            0 :                                     s_surf->SurfWinA(BackSurfNum, Lay) +=
    8296            0 :                                         BOverlap * state.dataSolarShading->SurfWinAbsBeamEQL(Lay) /
    8297            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
    8298              :                                 }
    8299              : 
    8300              :                                 // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
    8301              : 
    8302            0 :                                 BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
    8303            0 :                                 backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
    8304            0 :                                 state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
    8305            0 :                                     backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
    8306              : 
    8307              :                                 // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
    8308              :                                 // this beam radiation is categorized as diffuse radiation in the adjacent zone.
    8309              : 
    8310            0 :                                 int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
    8311            0 :                                 if (AdjSurfNum > 0) {
    8312            0 :                                     int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    8313            0 :                                     state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
    8314            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
    8315            0 :                                         BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
    8316            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
    8317            0 :                                         s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    8318              :                                 }
    8319              :                             } // End of check if back surface is opaque or window
    8320            0 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
    8321            0 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
    8322            0 :                                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    8323              :                         } // End of loop over back surfaces
    8324              : 
    8325              :                         //  *****************************
    8326              : 
    8327              :                     } // IF (SurfaceWindow(SurfNum)%WindowModelType /= WindowModel:: BSDF) THEN
    8328              :                 } else { // Simple interior solar distribution. All beam from exterior windows falls on floor;
    8329              :                     // some of this is absorbed/transmitted, rest is reflected to other surfaces.
    8330              : 
    8331       187294 :                     for (int const FloorNum : thisEnclosure.SurfacePtr) {
    8332              :                         // In following, ISABSF is zero except for nominal floor surfaces
    8333       174508 :                         if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) {
    8334       155283 :                             continue; // Keep only floor surfaces
    8335              :                         }
    8336        19225 :                         int const FlConstrNum = s_surf->SurfActiveConstruction(FloorNum);
    8337              : 
    8338        19225 :                         Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult; //[m2]
    8339        19225 :                         Real64 AbsBeamTotWin = 0.0;
    8340              : 
    8341        19225 :                         if (state.dataConstruction->Construct(FlConstrNum).TransDiff <= 0.0) {
    8342              :                             // Opaque surface
    8343        19224 :                             s_surf->SurfOpaqAI(FloorNum) +=
    8344        19224 :                                 BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
    8345              :                         } else {
    8346              :                             // Window
    8347              : 
    8348              :                             // Note that diffuse solar absorptance is used here for floor windows even though we're
    8349              :                             // dealing with incident beam radiation. This is because, for this simple interior distribution,
    8350              :                             // the beam radiation from exterior windows is assumed to be uniformly distributed over the
    8351              :                             // floor and so it makes no sense to use directional absorptances. Note also that floor windows
    8352              :                             // are assumed to not have blinds or shades in this calculation.
    8353              :                             // For the case of the floor window a complex fenestration (strange situation) the correct back
    8354              :                             // diffuse layer absorptions have already been put into the construction
    8355              : 
    8356            3 :                             for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
    8357            2 :                                 AbsBeamTotWin += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay);
    8358              :                             }
    8359              :                             // In the following we have to multiply by the AbsDiffBack(Lay)/AbsBeamTotWin ratio to get the
    8360              :                             // layer by layer absorbed beam since ISABSF(FloorNum) is proportional to AbsBeamTotWin
    8361              :                             // (see ComputeIntSolarAbsorpFactors).
    8362              : 
    8363            3 :                             for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
    8364            4 :                                 s_surf->SurfWinA(FloorNum, Lay) += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay) / AbsBeamTotWin *
    8365            2 :                                                                    BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) /
    8366            2 :                                                                    s_surf->Surface(FloorNum).Area; //[-]
    8367              :                             }
    8368              :                         }
    8369              : 
    8370        19225 :                         BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum); //[m2]
    8371              : 
    8372        19225 :                         int AdjSurfNum = s_surf->Surface(FloorNum).ExtBoundCond;
    8373        19225 :                         if (state.dataConstruction->Construct(FlConstrNum).TransDiff > 0.0 && AdjSurfNum > 0) {
    8374              : 
    8375              :                             // Window in an interior floor
    8376              : 
    8377            0 :                             int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    8378              : 
    8379              :                             // Contribution (assumed diffuse) to adjacent zone of beam radiation passing
    8380              :                             // through this window
    8381            0 :                             state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
    8382            0 :                                                                                    state.dataConstruction->Construct(FlConstrNum).TransDiff /
    8383              :                                                                                    AbsBeamTotWin;
    8384              : 
    8385            0 :                             BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
    8386            0 :                                         state.dataConstruction->Construct(FlConstrNum).TransDiff / AbsBeamTotWin;
    8387              :                         }
    8388              : 
    8389              :                     } // End of loop over floor sections
    8390              :                 } // End of check on complex vs. simple interior solar distribution
    8391              : 
    8392              :             } // End of sunlit fraction > 0 test
    8393              :         } // End of first loop over surfaces in zone
    8394              : 
    8395       105310 :         Real64 BABSZoneSSG = 0.0; // Beam radiation from exterior windows absorbed in a zone (only for scheduled surface gains)
    8396       105310 :         Real64 BTOTZoneSSG = 0.0; // Solar entering a zone in case of scheduled surface gains
    8397       105310 :         for (int iSSG = 1; iSSG <= s_surf->TotSurfIncSolSSG; ++iSSG) {
    8398            0 :             int SurfNum = s_surf->SurfIncSolSSG(iSSG).SurfPtr;
    8399            0 :             auto &surf = s_surf->Surface(SurfNum);
    8400              :             // do calculation only if construction number match.
    8401            0 :             if (s_surf->SurfIncSolSSG(iSSG).ConstrPtr == surf.Construction) {
    8402            0 :                 if (surf.SolarEnclIndex == enclosureNum) {
    8403            0 :                     Real64 AbsIntSurf = state.dataConstruction->Construct(surf.Construction).InsideAbsorpSolar;
    8404              :                     // SolarIntoZone = GetCurrentScheduleValue(SurfIncSolSSG(iSSG)%SchedPtr) * Surface(SurfNum)%Area
    8405            0 :                     Real64 SolarIntoZone = s_surf->SurfIncSolSSG(iSSG).sched->getCurrentVal(); // Solar radiation into zone to current surface
    8406            0 :                     s_surf->SurfOpaqAI(SurfNum) = SolarIntoZone * AbsIntSurf;
    8407            0 :                     BABSZoneSSG += s_surf->SurfOpaqAI(SurfNum) * surf.Area;
    8408            0 :                     BTOTZoneSSG += SolarIntoZone * surf.Area;
    8409              :                 }
    8410              :             }
    8411              :         }
    8412       105310 :         state.dataHeatBal->EnclSolDBSSG(enclosureNum) = BTOTZoneSSG - BABSZoneSSG;
    8413       105310 :         state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
    8414              : 
    8415       105310 :         if (state.dataHeatBal->EnclSolDB(enclosureNum) < 0.0) {
    8416            0 :             state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    8417              :         }
    8418              : 
    8419              :         // Variables for reporting
    8420       716999 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    8421       611689 :             auto &surf = s_surf->Surface(SurfNum);
    8422              : 
    8423       611689 :             Real64 SurfIncSolarMultiplier = surf.IncSolMultiplier;
    8424       611689 :             Real64 currBeamSolarRad = state.dataEnvrn->BeamSolarRad * SurfIncSolarMultiplier;
    8425       611689 :             Real64 currDifSolarRad = state.dataEnvrn->DifSolarRad * SurfIncSolarMultiplier;
    8426       611689 :             Real64 currGndSolarRad = state.dataEnvrn->GndSolarRad * SurfIncSolarMultiplier;
    8427       611689 :             if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
    8428        78961 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) *= currBeamSolarRad;
    8429        78961 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
    8430        78961 :                     state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8431        78961 :                 state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) =
    8432        78961 :                     state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) / (surf.Area + s_surf->SurfWinDividerArea(SurfNum));
    8433              :             } else { // Simple interior solar distribution. All beam falls on floor.
    8434       532728 :                 if (state.dataSolarShading->SurfIntAbsFac(SurfNum) > 0.0 && surf.HeatTransSurf) {
    8435       104432 :                     if (thisEnclosure.FloorArea > 0.0) {
    8436              :                         // spread onto all floor surfaces, these may or may not be called "floor"
    8437       104432 :                         state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.FloorArea;
    8438            0 :                     } else if (thisEnclosure.TotalSurfArea > 0.0) {
    8439              :                         // spread onto all interior surfaces
    8440            0 :                         state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.TotalSurfArea;
    8441              :                     } else { // divide be zero otherwise
    8442            0 :                         state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
    8443              :                     }
    8444              :                 }
    8445       532728 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = surf.Area * state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum);
    8446       532728 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
    8447       532728 :                     state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8448              :             }
    8449       611689 :             if (surf.Class == SurfaceClass::Window || surf.Class == SurfaceClass::TDD_Dome) {
    8450              : 
    8451        31116 :                 s_surf->SurfWinIntBeamAbsByShade(SurfNum) = state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum);
    8452        31116 :                 s_surf->SurfWinExtBeamAbsByShade(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum);
    8453              : 
    8454        31116 :                 if ((surf.ExtBoundCond == ExternalEnvironment) || (surf.ExtBoundCond == OtherSideCondModeledExt)) {
    8455              : 
    8456        31116 :                     WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
    8457        31116 :                     int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
    8458        31116 :                     int OutShelfSurf = 0;
    8459        31116 :                     if (ShelfNum > 0) { // Outside daylighting shelf
    8460            0 :                         OutShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).OutSurf;
    8461              :                     }
    8462              : 
    8463              :                     // This lookup may be avoid if this 2nd surf loop can be combined with the 1st
    8464        31116 :                     if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    8465            0 :                         int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    8466            0 :                         int SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    8467            0 :                         Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8468              :                         // Exterior diffuse solar incident on window (W/m2)
    8469            0 :                         Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum2) +
    8470            0 :                                              currGndSolarRad * s_surf->Surface(SurfNum2).ViewFactorGround;
    8471              :                         // Exterior diffuse sky solar transmitted by TDD (W/m2)
    8472            0 :                         Real64 SkySolarTrans = currDifSolarRad * TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso) *
    8473            0 :                                                state.dataSolarShading->SurfAnisoSkyMult(SurfNum2);
    8474              :                         // Exterior diffuse ground solar transmitted by TDD (W/m2)
    8475            0 :                         Real64 GndSolarTrans = currGndSolarRad * state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolIso *
    8476            0 :                                                s_surf->Surface(SurfNum2).ViewFactorGround;
    8477              : 
    8478            0 :                         s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
    8479            0 :                         s_surf->SurfWinDifSolar(SurfNum) = SkySolarTrans * surf.Area + GndSolarTrans * surf.Area;
    8480            0 :                         s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8481            0 :                         s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8482              : 
    8483            0 :                         s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
    8484            0 :                         s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8485              : 
    8486            0 :                         state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransmittedSolar = s_surf->SurfWinTransSolar(SurfNum);
    8487              :                         // TDDPipe(PipeNum)%TransSolBeam = TBmBm ! Reported above
    8488            0 :                         if (DifSolarInc > 0) {
    8489            0 :                             state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = (SkySolarTrans + GndSolarTrans) / DifSolarInc;
    8490              :                         } else {
    8491            0 :                             state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = 0.0;
    8492              :                         }
    8493              : 
    8494        31116 :                     } else if (OutShelfSurf > 0) { // Outside daylighting shelf
    8495              :                         Real64 ShelfSolarRad =
    8496            0 :                             (currBeamSolarRad *
    8497            0 :                                  state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) *
    8498            0 :                                  state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) +
    8499            0 :                              currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(OutShelfSurf)) *
    8500            0 :                             state.dataDaylightingDevicesData->Shelf(ShelfNum).OutReflectSol;
    8501              : 
    8502            0 :                         Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum) +
    8503            0 :                                              currGndSolarRad * surf.ViewFactorGround +
    8504            0 :                                              ShelfSolarRad * state.dataDaylightingDevicesData->Shelf(ShelfNum).ViewFactor;
    8505              : 
    8506            0 :                         s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
    8507            0 :                         s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
    8508            0 :                         s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8509            0 :                         s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8510              : 
    8511            0 :                         s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
    8512            0 :                         s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8513              : 
    8514              :                     } else { // Regular window
    8515        31116 :                         Real64 SkySolarInc = s_surf->SurfSkySolarInc(SurfNum);
    8516        31116 :                         Real64 GndSolarInc = s_surf->SurfGndSolarInc(SurfNum);
    8517        31116 :                         Real64 DifSolarInc = SkySolarInc + GndSolarInc;
    8518        31116 :                         s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
    8519              :                         // Note: for complex fenestration, SurfWinTransDifSolar has previously been defined using the effective
    8520              :                         // transmittance for sky and ground diffuse radiation (including beam radiation reflected from the ground)
    8521              :                         // so these calculations should be correct
    8522        31116 :                         s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
    8523        31116 :                         s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8524        31116 :                         s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8525        31116 :                         if (ANY_BLIND(ShadeFlag)) {
    8526            0 :                             auto const &surfShade = s_surf->surfShades(SurfNum);
    8527            0 :                             auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    8528            0 :                             assert(matBlind != nullptr);
    8529            0 :                             if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
    8530            0 :                                 s_surf->SurfWinDifSolar(SurfNum) = SkySolarInc * state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) +
    8531            0 :                                                                    GndSolarInc * state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum);
    8532            0 :                                 s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8533              :                             }
    8534              :                         }
    8535              : 
    8536        31116 :                         s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
    8537        31116 :                         s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8538              :                     }
    8539              : 
    8540              :                     // added TH 12/9/2009, CR 7907 & 7809
    8541        31116 :                     s_surf->SurfWinBmBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum);
    8542              : 
    8543        31116 :                     s_surf->SurfWinBmDifSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum);
    8544        31116 :                     s_surf->SurfWinBmBmSolarEnergy(SurfNum) = s_surf->SurfWinBmBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8545        31116 :                     s_surf->SurfWinBmDifSolarEnergy(SurfNum) = s_surf->SurfWinBmDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8546              : 
    8547              :                     // Solar not added by TDD:DOME; added to zone via TDD:DIFFUSER
    8548        31116 :                     if (surf.Class != SurfaceClass::TDD_Dome) {
    8549        31116 :                         state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
    8550        31116 :                         state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
    8551        31116 :                             state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8552        31116 :                         state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
    8553        31116 :                         state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
    8554        31116 :                         state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
    8555        31116 :                             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8556        31116 :                         state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
    8557        31116 :                             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8558              :                     }
    8559              :                 }
    8560              :             }
    8561              :         } // End of second loop over surfaces in zone
    8562              : 
    8563              :     } // End of first zone loop
    8564              : 
    8565              :     // Add interior window contribution to EnclSolDB
    8566              : 
    8567       176530 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    8568       105310 :         state.dataHeatBal->EnclSolDB(enclosureNum) += state.dataHeatBal->EnclSolDBIntWin(enclosureNum);
    8569       105310 :         state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) = state.dataHeatBal->EnclSolDBIntWin(enclosureNum) * state.dataEnvrn->BeamSolarRad;
    8570       105310 :         state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum) =
    8571       105310 :             state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8572              :     }
    8573              : 
    8574              :     // RJH - Calculate initial distribution of diffuse solar transmitted by exterior windows into each zone
    8575              :     //       to all interior surfaces in the zone
    8576              :     //       Includes subsequent transmittance of diffuse solar to adjacent zones through interior windows
    8577        71220 :     CalcWinTransDifSolInitialDistribution(state);
    8578        71220 : }
    8579            0 : void CalcAbsorbedOnExteriorOpaqueSurfaces(EnergyPlusData &state)
    8580              : {
    8581              :     // SUBROUTINE INFORMATION:
    8582              :     //       AUTHOR         Simon Vidanovic
    8583              :     //       DATE WRITTEN   May 2017
    8584              :     //       MODIFIED       na
    8585              :     //       RE-ENGINEERED  na
    8586              : 
    8587              :     // PURPOSE OF THIS SUBROUTINE:
    8588              :     // Calculates solar energy absorbed on exterior opaque surfaces
    8589              : 
    8590            0 :     auto &s_surf = state.dataSurface;
    8591              : 
    8592            0 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    8593            0 :         for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    8594            0 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    8595            0 :             for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    8596            0 :                 auto &surf = s_surf->Surface(SurfNum);
    8597              :                 // TH added 3/24/2010 while debugging CR 7872
    8598            0 :                 if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    8599            0 :                     continue;
    8600              :                 }
    8601            0 :                 int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    8602            0 :                 int SurfNum2 = SurfNum;
    8603            0 :                 if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    8604            0 :                     int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    8605            0 :                     SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    8606              :                 }
    8607            0 :                 Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8608            0 :                 Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8609              : 
    8610              :                 //-------------------------------------------------------------------------
    8611              :                 // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
    8612              :                 //-------------------------------------------------------------------------
    8613              : 
    8614            0 :                 if (SunLitFract > 0.0 && state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) {
    8615            0 :                     s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
    8616              : 
    8617              :                     // Note: movable insulation, if present, is accounted for in subr. InitIntSolarDistribution,
    8618              :                     // where SurfQRadSWOutMvIns is calculated from SurfOpaqQRadSWOutAbs and insulation solar absorptance
    8619              :                 }
    8620              :             }
    8621            0 :         }
    8622              :     }
    8623            0 : }
    8624              : 
    8625            0 : void CalcInteriorSolarDistributionWCESimple(EnergyPlusData &state)
    8626              : {
    8627              : 
    8628              :     // SUBROUTINE INFORMATION:
    8629              :     //       AUTHOR         Simon Vidanovic
    8630              :     //       DATE WRITTEN   May 2017
    8631              : 
    8632              :     // PURPOSE OF THIS SUBROUTINE:
    8633              :     // For a time step, calculates solar radiation absorbed by window layers, sky and diffuse solar
    8634              :     // gain into zone from exterior window, beam solar on exterior window transmitted as beam and/or diffuse
    8635              :     // and interior beam from exterior window that is absorbed/transmitted by back surfaces
    8636              : 
    8637              :     using namespace MultiLayerOptics;
    8638              : 
    8639            0 :     auto &s_surf = state.dataSurface;
    8640              : 
    8641            0 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    8642            0 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    8643            0 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    8644            0 :             int const firstSurf = thisSpace.HTSurfaceFirst;
    8645            0 :             int const lastSurf = thisSpace.HTSurfaceLast;
    8646            0 :             for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    8647            0 :                 s_surf->SurfOpaqAI(surfNum) = 0.0;
    8648            0 :                 s_surf->SurfOpaqAO(surfNum) = 0.0;
    8649              :             }
    8650            0 :         }
    8651              :     }
    8652              : 
    8653            0 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    8654              : 
    8655            0 :         Real64 BABSZone = 0;
    8656            0 :         Real64 BTOTZone = 0;
    8657            0 :         state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    8658            0 :         state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
    8659            0 :         state.dataHeatBal->ZoneTransSolar(enclosureNum) = 0;
    8660            0 :         state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) = 0;
    8661            0 :         state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) = 0;
    8662            0 :         state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) = 0;
    8663            0 :         state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) = 0;
    8664            0 :         state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) = 0;
    8665            0 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
    8666              : 
    8667            0 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    8668            0 :             auto &surf = s_surf->Surface(SurfNum);
    8669            0 :             if (surf.Class != SurfaceClass::Window) {
    8670            0 :                 continue;
    8671              :             }
    8672            0 :             int SurfNum2 = 0;
    8673            0 :             if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    8674            0 :                 int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    8675            0 :                 SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    8676              :             } else {
    8677            0 :                 SurfNum2 = SurfNum;
    8678              :             }
    8679            0 :             auto &window = s_surf->SurfaceWindow(SurfNum2);
    8680            0 :             Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2); // Note: surfnum 2
    8681            0 :             Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8682              : 
    8683            0 :             std::pair<Real64, Real64> incomingAngle = getSunWCEAngles(state, SurfNum2, BSDFDirection::Incoming);
    8684            0 :             Real64 Theta = incomingAngle.first;
    8685            0 :             Real64 Phi = incomingAngle.second;
    8686              : 
    8687            0 :             int ConstrNum = s_surf->Surface(SurfNum2).Construction;
    8688            0 :             if (s_surf->Surface(SurfNum2).activeShadedConstruction > 0) {
    8689            0 :                 ConstrNum = s_surf->Surface(SurfNum2).activeShadedConstruction;
    8690              :             }
    8691              :             auto aLayer = // (AUTO_OK_OBJ)
    8692            0 :                 CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, WavelengthRange::Solar, ConstrNum);
    8693              : 
    8694              :             ///////////////////////////////////////////////
    8695              :             // Solar absorbed in window layers
    8696              :             ///////////////////////////////////////////////
    8697            0 :             if (state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2) > 0.0) {
    8698            0 :                 size_t numOfLayers = aLayer->getNumOfLayers();
    8699            0 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    8700            0 :                     int CurrentState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState;
    8701            0 :                     auto &cplxState = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurrentState);
    8702            0 :                     for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
    8703              :                         // Simon: Important note about this equation is to use BeamSolarRad and not SurfQRadSWOutIncident
    8704              :                         // is because BeamSolarRad is direct normal radiation (looking at the Sun) while SurfRadSWOutIncident
    8705              :                         // is normal to window incidence. Since BSDF coefficients are taking into account angle of incidence,
    8706              :                         // BeamSolarRad should be used in this case
    8707            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) =
    8708            0 :                             cplxState.WinSkyFtAbs(Lay) * s_surf->SurfSkySolarInc(SurfNum2) +
    8709            0 :                             cplxState.WinSkyGndAbs(Lay) * s_surf->SurfGndSolarInc(SurfNum2) +
    8710            0 :                             s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad +
    8711            0 :                             s_surf->SurfWinACFOverlap(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
    8712            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
    8713            0 :                         s_surf->SurfWinADiffFront(SurfNum, Lay) = cplxState.WinSkyGndAbs(Lay);
    8714              :                     }
    8715              :                 } else {
    8716            0 :                     for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
    8717            0 :                         Real64 AbWinBeam = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Direct, Theta, Phi) *
    8718            0 :                                            window.OutProjSLFracMult[state.dataGlobal->HourOfDay];
    8719            0 :                         Real64 AbWinDiffFront = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Diffuse, Theta, Phi);
    8720              :                         //                        Real64 AbWinDiffBack = aLayer->getAbsorptanceLayer(Lay, Side::Back, ScatteringSimple::Diffuse,
    8721              :                         //                        Theta, Phi);
    8722              : 
    8723              :                         // Simon: This should not be multiplied with cosine of incident angle. This however gives same
    8724              :                         // results as BSDF and Winkelmann models.
    8725            0 :                         s_surf->SurfWinA(SurfNum, Lay) =
    8726            0 :                             AbWinBeam * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
    8727            0 :                         s_surf->SurfWinADiffFront(SurfNum, Lay) = AbWinDiffFront;
    8728              : 
    8729              :                         // Simon: Same not as for BSDF. Normal solar radiation should be taken here because angle of
    8730              :                         // incidence is already taken into account
    8731            0 :                         Real64 absBeam = s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
    8732              :                         Real64 absDiff =
    8733            0 :                             s_surf->SurfWinADiffFront(SurfNum, Lay) * (s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2));
    8734            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) = (absBeam + absDiff);
    8735            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
    8736              :                     }
    8737              :                 }
    8738              :             }
    8739              : 
    8740              :             ////////////////////////////////////////////////////////////////////
    8741              :             // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
    8742              :             ////////////////////////////////////////////////////////////////////
    8743            0 :             constexpr Real64 minLambda{0.3};
    8744            0 :             constexpr Real64 maxLambda{2.5};
    8745              :             const Real64 Tdiff =
    8746            0 :                 aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DiffuseDiffuse, Theta, Phi);
    8747            0 :             state.dataConstruction->Construct(ConstrNum).TransDiff = Tdiff;
    8748            0 :             Real64 EnclSolDSWin = s_surf->SurfSkySolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
    8749            0 :             if ((state.dataEnvrn->DifSolarRad != 0)) {
    8750            0 :                 EnclSolDSWin /= state.dataEnvrn->DifSolarRad;
    8751              :             } else {
    8752            0 :                 EnclSolDSWin /= 1e-8;
    8753              :             }
    8754              : 
    8755            0 :             Real64 EnclSolDGWin = s_surf->SurfGndSolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
    8756            0 :             (state.dataEnvrn->GndSolarRad != 0) ? EnclSolDGWin /= state.dataEnvrn->GndSolarRad : EnclSolDGWin /= 1e-8;
    8757              : 
    8758              :             ////////////////////////////////////////////////////////////////////
    8759              :             // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
    8760              :             ////////////////////////////////////////////////////////////////////
    8761            0 :             Real64 TBmBm = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDirect, Theta, Phi);
    8762            0 :             Real64 TBmDif = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDiffuse, Theta, Phi);
    8763            0 :             Real64 SurfWinTransBmBmSolar = TBmBm * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    8764            0 :             Real64 SurfWinTransBmDifSolar = TBmDif * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    8765            0 :             BTOTZone += SurfWinTransBmBmSolar + SurfWinTransBmDifSolar;
    8766              : 
    8767            0 :             Real64 DifSolarRadiation = s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2);
    8768            0 :             s_surf->SurfWinBmSolar(SurfNum) = state.dataEnvrn->BeamSolarRad * (TBmBm + TBmDif) * surf.Area * CosInc;
    8769            0 :             s_surf->SurfWinDifSolar(SurfNum) = DifSolarRadiation * Tdiff * surf.Area;
    8770            0 :             s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8771            0 :             s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8772            0 :             s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum);
    8773            0 :             s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8774              : 
    8775              :             // Add beam solar absorbed by outside reveal to outside of window's base surface.
    8776              :             // Add beam solar absorbed by inside reveal to inside of window's base surface.
    8777              :             // This ignores 2-D heat transfer effects.
    8778            0 :             int BaseSurfNum = surf.BaseSurf;
    8779            0 :             s_surf->SurfOpaqAI(BaseSurfNum) = s_surf->SurfWinBmSolAbsdInsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
    8780            0 :             s_surf->SurfOpaqAO(BaseSurfNum) = s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
    8781              : 
    8782              :             ////////////////////////////////////////////////////////////////////
    8783              :             // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
    8784              :             ////////////////////////////////////////////////////////////////////
    8785            0 :             Real64 TBm = TBmBm;
    8786              :             // Correction for beam absorbed by inside reveal
    8787            0 :             Real64 TBmDenom = SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    8788            0 :             if (TBmDenom != 0.0) { // when =0.0, no correction
    8789            0 :                 TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
    8790              :             }
    8791              : 
    8792            0 :             TBm = max(0.0, TBm);
    8793            0 :             TBm *= surf.IncSolMultiplier;
    8794              : 
    8795            0 :             int NumOfBackSurf = state.dataShadowComb->ShadowComb(BaseSurfNum).NumBackSurf;
    8796              : 
    8797            0 :             if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
    8798            0 :                 for (int IBack = 1; IBack <= NumOfBackSurf; ++IBack) {
    8799              : 
    8800              :                     int const BackSurfNum =
    8801            0 :                         state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8802              : 
    8803            0 :                     if (BackSurfNum == 0) {
    8804            0 :                         break; // No more irradiated back surfaces for this exterior window
    8805              :                     }
    8806            0 :                     int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
    8807            0 :                     auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    8808              :                     // NBackGlass = Construct( ConstrNumBack ).TotGlassLayers;
    8809              :                     // Irradiated (overlap) area for this back surface, projected onto window plane
    8810              :                     // (includes effect of shadowing on exterior window)
    8811            0 :                     Real64 AOverlap = state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8812            0 :                     Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
    8813              : 
    8814            0 :                     if (constrBack.TransDiff <= 0.0) {
    8815              :                         // Back surface is opaque interior or exterior wall
    8816              : 
    8817            0 :                         Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
    8818            0 :                         s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
    8819            0 :                         BABSZone += BOverlap * AbsIntSurf;                                                            //[m2]
    8820              :                     }
    8821              :                 }
    8822              :             } else {
    8823            0 :                 for (int const FloorNum : thisEnclosure.SurfacePtr) {
    8824              :                     // In following, ISABSF is zero except for nominal floor surfaces
    8825            0 :                     if (!s_surf->Surface(FloorNum).HeatTransSurf) {
    8826            0 :                         continue;
    8827              :                     }
    8828            0 :                     if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) {
    8829            0 :                         continue; // Keep only floor surfaces
    8830              :                     }
    8831              : 
    8832            0 :                     Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay]; //[m2]
    8833              : 
    8834            0 :                     if (state.dataConstruction->Construct(s_surf->Surface(FloorNum).Construction).TransDiff <= 0.0) {
    8835              :                         // Opaque surface
    8836            0 :                         s_surf->SurfOpaqAI(FloorNum) +=
    8837            0 :                             BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
    8838              :                     }
    8839              :                 }
    8840              :             }
    8841            0 :             state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
    8842            0 :             state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
    8843            0 :                 state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8844            0 :             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
    8845            0 :             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
    8846            0 :             state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
    8847            0 :                 state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8848            0 :             state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
    8849            0 :                 state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8850            0 :         }
    8851            0 :         state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
    8852              :     }
    8853            0 : }
    8854              : 
    8855            0 : int WindowScheduledSolarAbs(EnergyPlusData &state,
    8856              :                             int const SurfNum, // Surface number
    8857              :                             int const ConstNum // Construction number
    8858              : )
    8859              : {
    8860              :     // SUBROUTINE INFORMATION:
    8861              :     //       AUTHOR         Simon Vidanovic
    8862              :     //       DATE WRITTEN   June 2013
    8863              : 
    8864              :     // PURPOSE OF THIS SUBROUTINE:
    8865              :     // Returns scheduled surface gain object for given surface-construction combination
    8866            0 :     auto &s_surf = state.dataSurface;
    8867              : 
    8868            0 :     for (int i = 1; i <= s_surf->TotFenLayAbsSSG; ++i) {
    8869            0 :         if ((s_surf->FenLayAbsSSG(i).SurfPtr == SurfNum) && (s_surf->FenLayAbsSSG(i).ConstrPtr == ConstNum)) {
    8870            0 :             return i;
    8871              :         }
    8872              :     }
    8873              : 
    8874            0 :     return 0;
    8875              : }
    8876              : 
    8877       580565 : int SurfaceScheduledSolarInc(EnergyPlusData &state,
    8878              :                              int const SurfNum, // Surface number
    8879              :                              int const ConstNum // Construction number
    8880              : )
    8881              : {
    8882              :     // SUBROUTINE INFORMATION:
    8883              :     //       AUTHOR         Simon Vidanovic
    8884              :     //       DATE WRITTEN   June 2013
    8885              : 
    8886              :     // PURPOSE OF THIS SUBROUTINE:
    8887              :     // Returns scheduled surface gain pointer for given surface-construction combination
    8888              : 
    8889       580565 :     auto &s_surf = state.dataSurface;
    8890              : 
    8891       580577 :     for (int i = 1; i <= s_surf->TotSurfIncSolSSG; ++i) {
    8892           15 :         if ((s_surf->SurfIncSolSSG(i).SurfPtr == SurfNum) && (s_surf->SurfIncSolSSG(i).ConstrPtr == ConstNum)) {
    8893            3 :             return i;
    8894              :         }
    8895              :     }
    8896              : 
    8897       580562 :     return 0;
    8898              : }
    8899              : 
    8900         3643 : void PerformSolarCalculations(EnergyPlusData &state)
    8901              : {
    8902              : 
    8903              :     // SUBROUTINE INFORMATION:
    8904              :     //       AUTHOR         Linda K. Lawrie
    8905              :     //       DATE WRITTEN   July 1999
    8906              :     //       MODIFIED       Sept 2003, FCW: add calls to CalcBeamSolDiffuseReflFactors and
    8907              :     //                       CalcBeamSolSpecularReflFactors
    8908              :     //                      Jan 2004, FCW: call CalcDayltgCoefficients if storm window status on
    8909              :     //                       any window has changed
    8910              :     //       RE-ENGINEERED  na
    8911              : 
    8912              :     // PURPOSE OF THIS SUBROUTINE:
    8913              :     // This subroutine determines if new solar/shading calculations need
    8914              :     // to be performed and calls the proper routines to do the job.
    8915              : 
    8916              :     // METHODOLOGY EMPLOYED:
    8917              :     // Users are allowed to enter a value for number of days in each period that
    8918              :     // will be used for calculating solar.  (Later, this could be more complicated as
    8919              :     // in allowing a number of days in a month or something).  Using this value or the
    8920              :     // default (20 days) if nothing is entered by the user, the routine will use the
    8921              :     // number of days left to determine if a new set of calculations should be done.
    8922              :     // The calculations use the average of "equation of time" and "solar declination"
    8923              :     // to perform the calculations.
    8924              : 
    8925              :     // REFERENCES:
    8926              :     // na
    8927              : 
    8928              :     // Using/Aliasing
    8929              :     using Dayltg::CalcDayltgCoefficients;
    8930              :     // Locals
    8931              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    8932              :     // na
    8933              : 
    8934              :     // SUBROUTINE PARAMETER DEFINITIONS:
    8935              :     // na
    8936              : 
    8937              :     // INTERFACE BLOCK SPECIFICATIONS
    8938              :     // na
    8939              : 
    8940              :     // DERIVED TYPE DEFINITIONS
    8941              :     // na
    8942              : 
    8943              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8944              :     Real64 SumDec;
    8945              :     Real64 SumET;
    8946              :     Real64 AvgEqOfTime;
    8947              :     Real64 AvgSinSolarDeclin;
    8948              :     Real64 AvgCosSolarDeclin;
    8949              :     int PerDayOfYear;
    8950              :     int Count;
    8951              :     Real64 SinDec;
    8952              :     Real64 EqTime;
    8953              :     // not used INTEGER SurfNum
    8954              : 
    8955         3643 :     auto &s_surf = state.dataSurface;
    8956              :     // Calculate sky diffuse shading
    8957              : 
    8958         3643 :     if (state.dataGlobal->BeginSimFlag) {
    8959          104 :         state.dataSolarShading->CalcSkyDifShading = true;
    8960          104 :         SkyDifSolarShading(state); // Calculate factors for shading of sky diffuse solar
    8961          104 :         state.dataSolarShading->CalcSkyDifShading = false;
    8962              :     }
    8963              : 
    8964         3643 :     if (state.dataGlobal->BeginEnvrnFlag) {
    8965          481 :         state.dataSolarShading->ShadowingDaysLeft = 0;
    8966              :     }
    8967              : 
    8968         3643 :     if (state.dataSolarShading->ShadowingDaysLeft <= 0 || state.dataSysVars->DetailedSolarTimestepIntegration) {
    8969              : 
    8970         1836 :         if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    8971              :             //  Perform calculations.
    8972          478 :             state.dataSolarShading->ShadowingDaysLeft = state.dataSolarShading->ShadowingCalcFrequency;
    8973          478 :             if (state.dataGlobal->DayOfSim + state.dataSolarShading->ShadowingDaysLeft > state.dataGlobal->NumOfDayInEnvrn) {
    8974          458 :                 state.dataSolarShading->ShadowingDaysLeft = state.dataGlobal->NumOfDayInEnvrn - state.dataGlobal->DayOfSim + 1;
    8975              :             }
    8976              : 
    8977              :             //  Calculate average Equation of Time, Declination Angle for this period
    8978              : 
    8979          478 :             if (!state.dataGlobal->WarmupFlag) {
    8980            1 :                 if (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
    8981            1 :                     DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDyYr);
    8982              :                 } else {
    8983            0 :                     DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDy);
    8984              :                 }
    8985            1 :                 state.dataReportFlag->DisplayPerfSimulationFlag = true;
    8986              :             }
    8987              : 
    8988          478 :             PerDayOfYear = state.dataEnvrn->DayOfYear;
    8989          478 :             SumDec = 0.0;
    8990          478 :             SumET = 0.0;
    8991         1336 :             for (Count = 1; Count <= state.dataSolarShading->ShadowingDaysLeft; ++Count) {
    8992          858 :                 SUN3(PerDayOfYear, SinDec, EqTime);
    8993          858 :                 SumDec += SinDec;
    8994          858 :                 SumET += EqTime;
    8995          858 :                 ++PerDayOfYear;
    8996              :             }
    8997              : 
    8998              :             //  Compute Period Values
    8999          478 :             AvgSinSolarDeclin = SumDec / double(state.dataSolarShading->ShadowingDaysLeft);
    9000          478 :             AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
    9001          478 :             AvgEqOfTime = SumET / double(state.dataSolarShading->ShadowingDaysLeft);
    9002              :         } else {
    9003         1358 :             SUN3(state.dataEnvrn->DayOfYear, AvgSinSolarDeclin, AvgEqOfTime);
    9004         1358 :             AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
    9005              :             // trigger display of progress in the simulation every two weeks
    9006         1358 :             if (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && (state.dataGlobal->DayOfSim % 14 == 0)) {
    9007            0 :                 state.dataReportFlag->DisplayPerfSimulationFlag = true;
    9008              :             }
    9009              :         }
    9010              : 
    9011         1836 :         CalcPerSolarBeam(state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
    9012              : 
    9013              :         // Calculate factors for solar reflection
    9014         1836 :         if (s_surf->CalcSolRefl) {
    9015            0 :             CalcBeamSolDiffuseReflFactors(state);
    9016            0 :             CalcBeamSolSpecularReflFactors(state);
    9017            0 :             if (state.dataGlobal->BeginSimFlag) {
    9018            0 :                 CalcSkySolDiffuseReflFactors(state);
    9019              :             }
    9020              :         }
    9021              :         //  Calculate daylighting coefficients
    9022         1836 :         CalcDayltgCoefficients(state);
    9023              :     }
    9024              : 
    9025         3643 :     if (!state.dataGlobal->WarmupFlag) {
    9026          417 :         --state.dataSolarShading->ShadowingDaysLeft;
    9027              :     }
    9028              : 
    9029              :     // Recalculate daylighting coefficients if storm window has been added
    9030              :     // or removed from one or more windows at beginning of day
    9031         5005 :     if (state.dataDayltg->TotWindowsWithDayl > 0 && !state.dataGlobal->BeginSimFlag && !state.dataGlobal->BeginEnvrnFlag &&
    9032         5005 :         !state.dataGlobal->WarmupFlag && s_surf->TotStormWin > 0 && state.dataHeatBal->StormWinChangeThisDay) {
    9033            0 :         CalcDayltgCoefficients(state);
    9034              :     }
    9035         3643 : }
    9036              : 
    9037         8010 : void SHDRVL(EnergyPlusData &state,
    9038              :             int const HTSS,  // Heat transfer surface number of the subsurface
    9039              :             int const SBSNR, // Subsurface number
    9040              :             int const Hour,
    9041              :             int const TS)
    9042              : {
    9043              : 
    9044              :     // SUBROUTINE INFORMATION:
    9045              :     //       AUTHOR         Legacy Code
    9046              :     //       DATE WRITTEN
    9047              :     //       MODIFIED       May 2002 (FCW): allow triangular windows to have reveal.
    9048              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    9049              : 
    9050              :     // PURPOSE OF THIS SUBROUTINE:
    9051              :     // This subroutine computes the shadowing from a reveal onto a subsurface.
    9052              : 
    9053              :     // REFERENCES:
    9054              :     // BLAST/IBLAST code, original author George Walton
    9055              : 
    9056              :     int NVS; // Number of vertices
    9057              : 
    9058         8010 :     int constexpr None(0);                       // for use with RevealStatus
    9059         8010 :     int constexpr EntireWindowShadedByReveal(1); // for use with RevealStatus
    9060         8010 :     int constexpr WindowShadedOnlyByReveal(2);   // for use with RevealStatus
    9061              : 
    9062              :     Real64 A; // Area
    9063              :     Real64 R; // Depth of the reveal (m)
    9064              :     int I;    // Loop control
    9065              :     int N;    // Vertex number
    9066              :     int NS1;  // Locations in homogeneous coordinate array
    9067              :     int NS2;
    9068              :     // note, below dimensions not changed because subsurface still max 4
    9069         8010 :     Array1D<Real64> XVT(5); // Projected X coordinates of vertices
    9070         8010 :     Array1D<Real64> YVT(5); // Projected Y coordinates of vertices
    9071              :     bool RevealStatusSet;   // Used to control flow through this subroutine.
    9072              :     // Certain operations performed only if reveal status not yet set.
    9073              :     int RevealStatus; // Status of the reveal, takes the parameter values above
    9074              : 
    9075         8010 :     auto &s_surf = state.dataSurface;
    9076              : 
    9077         8010 :     RevealStatus = None;
    9078         8010 :     RevealStatusSet = false;
    9079              : 
    9080         8010 :     if (!state.dataSolarShading->CalcSkyDifShading) {
    9081         4994 :         state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = None;
    9082              :     }
    9083              : 
    9084         8010 :     R = s_surf->Surface(SBSNR).Reveal;
    9085         8010 :     if (R <= 0.0) {
    9086         8010 :         RevealStatus = None;
    9087         8010 :         RevealStatusSet = true;
    9088              :     }
    9089              : 
    9090         8010 :     if (!RevealStatusSet) {
    9091              : 
    9092            0 :         state.dataSolarShading->FRVLHC = state.dataSolarShading->LOCHCA + 1;
    9093            0 :         ++state.dataSolarShading->LOCHCA;
    9094            0 :         NVS = s_surf->Surface(SBSNR).Sides;
    9095              : 
    9096              :         // Currently (06May02) windows are either rectangles (NVS=4) or triangles (NVS=3)
    9097              : 
    9098            0 :         if (NVS == 4) { // Rectangular subsurface
    9099              : 
    9100              :             // Determine vertices of reveal.
    9101              :             // Project the subsurface up to the plane of the wall.
    9102              : 
    9103            0 :             XVT(1) = s_surf->ShadeV(SBSNR).XV(1) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
    9104            0 :             XVT(2) = s_surf->ShadeV(SBSNR).XV(2) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
    9105            0 :             XVT(3) = s_surf->ShadeV(SBSNR).XV(3) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
    9106            0 :             XVT(4) = s_surf->ShadeV(SBSNR).XV(4) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
    9107            0 :             YVT(1) = s_surf->ShadeV(SBSNR).YV(1) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
    9108            0 :             YVT(2) = s_surf->ShadeV(SBSNR).YV(2) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
    9109            0 :             YVT(3) = s_surf->ShadeV(SBSNR).YV(3) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
    9110            0 :             YVT(4) = s_surf->ShadeV(SBSNR).YV(4) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
    9111              : 
    9112              :             // Check for complete shadowing.
    9113              : 
    9114            0 :             if ((XVT(2) >= XVT(3)) || (YVT(2) >= YVT(1))) {
    9115              : 
    9116            0 :                 RevealStatus = EntireWindowShadedByReveal;
    9117            0 :                 RevealStatusSet = true;
    9118              : 
    9119              :             } else {
    9120              :                 // Re-order vertices to clockwise.
    9121              : 
    9122            0 :                 for (N = 1; N <= NVS; ++N) {
    9123            0 :                     state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
    9124            0 :                     state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
    9125              :                 }
    9126              : 
    9127              :                 // Transform to homogeneous coordinates
    9128              : 
    9129            0 :                 HTRANS1(state, state.dataSolarShading->FRVLHC, NVS);
    9130            0 :                 state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) = -state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
    9131            0 :                 state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
    9132              : 
    9133            0 :                 if (state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) <= 0.0) {
    9134            0 :                     RevealStatus = EntireWindowShadedByReveal;
    9135            0 :                     RevealStatusSet = true;
    9136              :                 }
    9137              :             }
    9138              : 
    9139            0 :         } else if (NVS == 3) { // Triangular window
    9140              : 
    9141              :             // Project window to outside plane of parent surface
    9142              : 
    9143            0 :             for (N = 1; N <= 3; ++N) {
    9144            0 :                 XVT(N) = s_surf->ShadeV(SBSNR).XV(N) + R * state.dataSolarShading->XShadowProjection;
    9145            0 :                 YVT(N) = s_surf->ShadeV(SBSNR).YV(N) + R * state.dataSolarShading->YShadowProjection;
    9146              :             }
    9147              : 
    9148              :             // Find the overlap between the original window and the projected window
    9149              :             // Put XVT,YVT in clockwise order
    9150              : 
    9151            0 :             for (N = 1; N <= NVS; ++N) {
    9152            0 :                 state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
    9153            0 :                 state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
    9154              :             }
    9155              : 
    9156              :             // Transform to homogeneous coordinates
    9157              : 
    9158            0 :             NS1 = state.dataSolarShading->LOCHCA + 1;
    9159            0 :             state.dataSolarShading->LOCHCA = NS1;
    9160            0 :             HTRANS1(state, NS1, NVS);
    9161              : 
    9162              :             // Put XV,YV in clockwise order
    9163              : 
    9164            0 :             for (N = 1; N <= NVS; ++N) {
    9165            0 :                 state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(NVS + 1 - N);
    9166            0 :                 state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(NVS + 1 - N);
    9167              :             }
    9168              : 
    9169              :             // Transform to homogeneous coordinates
    9170              : 
    9171            0 :             NS2 = state.dataSolarShading->LOCHCA + 1;
    9172            0 :             state.dataSolarShading->LOCHCA = NS2;
    9173            0 :             HTRANS1(state, NS2, NVS);
    9174            0 :             state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
    9175              : 
    9176              :             // Find overlap
    9177              : 
    9178            0 :             DeterminePolygonOverlap(state, NS1, NS2, state.dataSolarShading->FRVLHC);
    9179            0 :             if (state.dataSolarShading->OverlapStatus == NoOverlap) {
    9180            0 :                 RevealStatus = EntireWindowShadedByReveal;
    9181            0 :                 RevealStatusSet = true;
    9182              :             }
    9183              :         }
    9184              :     }
    9185              : 
    9186         8010 :     if (!RevealStatusSet) {
    9187              : 
    9188              :         // Check for no shadows on window.
    9189              : 
    9190            0 :         if (state.dataSolarShading->NSBSHC <= 1) {
    9191            0 :             RevealStatus = WindowShadedOnlyByReveal;
    9192            0 :             RevealStatusSet = true;
    9193              :         } else {
    9194              :             // Reduce all previous shadows to size of reveal opening.
    9195            0 :             state.dataSolarShading->LOCHCA = state.dataSolarShading->FRVLHC;
    9196            0 :             MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FSBSHC, state.dataSolarShading->NSBSHC - 1);
    9197            0 :             if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    9198            0 :                 RevealStatus = None;
    9199            0 :                 RevealStatusSet = true;
    9200              :             } else {
    9201            0 :                 state.dataSolarShading->NRVLHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FRVLHC + 1;
    9202            0 :                 if (state.dataSolarShading->NRVLHC <= 1) {
    9203            0 :                     RevealStatus = WindowShadedOnlyByReveal;
    9204            0 :                     RevealStatusSet = true;
    9205              :                 }
    9206              :             }
    9207              :         }
    9208              :     }
    9209              : 
    9210         8010 :     if (!RevealStatusSet) {
    9211              :         // Compute sunlit area.
    9212            0 :         A = state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
    9213            0 :         for (I = 2; I <= state.dataSolarShading->NRVLHC; ++I) {
    9214            0 :             A += state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC - 1 + I) *
    9215            0 :                  (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC - 1 + I));
    9216              :         }
    9217            0 :         state.dataSolarShading->SurfSunlitArea(HTSS) = A;
    9218              :     }
    9219              : 
    9220         8010 :     if ((RevealStatus == EntireWindowShadedByReveal) || (state.dataSolarShading->SurfSunlitArea(HTSS) < 0.0)) {
    9221            0 :         state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0; // Window entirely shaded by reveal.
    9222         8010 :     } else if (RevealStatus == WindowShadedOnlyByReveal) {
    9223            0 :         state.dataSolarShading->SurfSunlitArea(HTSS) =
    9224            0 :             state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC); // Window shaded only by reveal.
    9225              :     }
    9226              : 
    9227         8010 :     if (!state.dataSolarShading->CalcSkyDifShading) {
    9228         4994 :         state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = RevealStatus;
    9229              :     }
    9230         8010 : }
    9231              : 
    9232        90268 : void SHDSBS(EnergyPlusData &state,
    9233              :             int const iHour, // Hour Index
    9234              :             int const CurSurf,
    9235              :             int const NBKS, // Number of back surfaces
    9236              :             int const NSBS, // Number of subsurfaces
    9237              :             int const HTS,  // Heat transfer surface number of the general receiving surf
    9238              :             int const TS    // Time step Index
    9239              : )
    9240              : {
    9241              : 
    9242              :     // SUBROUTINE INFORMATION:
    9243              :     //       AUTHOR         Legacy Code
    9244              :     //       DATE WRITTEN
    9245              :     //       MODIFIED       FCW, Oct 2002: Surface%Area --> Surface%Area + SurfaceWindow%DividerArea
    9246              :     //                       in calculation of SunlitFracWithoutReveal (i.e., use full window area, not
    9247              :     //                       just glass area.
    9248              :     //                      TH, May 2009: Bug fixed to address part of CR 7596 - inside reveals
    9249              :     //                       causing high cooling loads
    9250              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    9251              : 
    9252              :     // PURPOSE OF THIS SUBROUTINE:
    9253              :     // This subroutine determines the shadowing on subsurfaces and
    9254              :     // revises the base surface area accordingly.  It also computes
    9255              :     // the effect of transparent subsurfaces.
    9256              : 
    9257              :     // REFERENCES:
    9258              :     // BLAST/IBLAST code, original author George Walton
    9259              : 
    9260              :     Real64 A;        // Area
    9261              :     int I;           // Loop control
    9262              :     int J;           // Loop control
    9263              :     int K;           // Window construction number
    9264              :     int N;           // Vertex number
    9265              :     Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
    9266              :     // For windows, includes divider area
    9267              :     //  REAL(r64) FrameAreaAdd    ! Additional frame area sunlit
    9268              :     //  REAL(r64) DividerAreaAdd  ! Additional frame area sunlit
    9269              :     int HTSS;  // Heat transfer surface number of the subsurface
    9270              :     int SBSNR; // Subsurface number
    9271              : 
    9272        90268 :     auto &s_surf = state.dataSurface;
    9273              : 
    9274        90268 :     if (NSBS > 0) { // Action taken only if subsurfaces present
    9275              : 
    9276        15470 :         state.dataSolarShading->FSBSHC = state.dataSolarShading->LOCHCA + 1;
    9277              : 
    9278        32628 :         for (I = 1; I <= NSBS; ++I) { // Do for all subsurfaces (sbs).
    9279              : 
    9280        17158 :             SBSNR = state.dataShadowComb->ShadowComb(CurSurf).SubSurf(I);
    9281              : 
    9282        17158 :             HTSS = SBSNR;
    9283              : 
    9284        17158 :             K = s_surf->Surface(SBSNR).Construction;
    9285              : 
    9286        17158 :             if (!state.dataSolarShading->penumbra) {
    9287        34316 :                 if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures) &&
    9288        17158 :                     (state.dataSolarShading->SurfSunlitArea(HTS) > 0.0)) {
    9289              : 
    9290              :                     // Re-order vertices to clockwise sequential; compute homogeneous coordinates.
    9291         8329 :                     state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
    9292        41645 :                     for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
    9293        33316 :                         state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
    9294        33316 :                         state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
    9295              :                     }
    9296         8329 :                     state.dataSolarShading->LOCHCA = state.dataSolarShading->FSBSHC;
    9297         8329 :                     HTRANS1(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->NVS);
    9298         8329 :                     state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
    9299         8329 :                     state.dataSolarShading->HCT(state.dataSolarShading->LOCHCA) = 1.0;
    9300         8329 :                     state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
    9301              : 
    9302              :                     // Determine sunlit area of subsurface due to shadows on general receiving surface.
    9303         8329 :                     if (state.dataSolarShading->NGSSHC > 0) {
    9304         2773 :                         MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FGSSHC - 1, state.dataSolarShading->NGSSHC);
    9305         2773 :                         if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures)) {
    9306         2773 :                             state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
    9307              :                         }
    9308              :                     }
    9309              :                 }
    9310              : 
    9311        34316 :                 if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures) ||
    9312        17158 :                     (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0)) { // General receiving surface totally shaded.
    9313              : 
    9314         8829 :                     state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9315              : 
    9316         8829 :                     if (iHour > 0 && TS > 0) {
    9317         4649 :                         state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) = 0.0;
    9318              :                     }
    9319              : 
    9320         8329 :                 } else if ((state.dataSolarShading->NGSSHC <= 0) || (state.dataSolarShading->NSBSHC == 1)) { // No shadows.
    9321              : 
    9322         5608 :                     state.dataSolarShading->SurfSunlitArea(HTSS) = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
    9323         5608 :                     state.dataSolarShading->SurfSunlitArea(HTS) -=
    9324         5608 :                         state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
    9325              : 
    9326              :                     // TH. This is a bug.  SunLitFracWithoutReveal should be a ratio of area
    9327              :                     // IF(IHour > 0 .AND. TS > 0) SunLitFracWithoutReveal(HTSS,IHour,TS) = &
    9328              :                     //      Surface(HTSS)%NetAreaShadowCalc
    9329              : 
    9330              :                     // new code fixed part of CR 7596. TH 5/29/2009
    9331         5608 :                     if (iHour > 0 && TS > 0) {
    9332         3452 :                         state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
    9333         3452 :                             state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).NetAreaShadowCalc;
    9334              :                     }
    9335              : 
    9336         5608 :                     SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
    9337              : 
    9338         5608 :                     if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    9339            0 :                         state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9340              :                     }
    9341              : 
    9342              :                 } else { // Compute area.
    9343              : 
    9344         2721 :                     A = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
    9345         6211 :                     for (J = 2; J <= state.dataSolarShading->NSBSHC; ++J) {
    9346         3490 :                         A += state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC - 1 + J) *
    9347         3490 :                              (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FSBSHC - 1 + J));
    9348              :                     }
    9349         2721 :                     state.dataSolarShading->SurfSunlitArea(HTSS) = A;
    9350         2721 :                     if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
    9351              : 
    9352         2402 :                         state.dataSolarShading->SurfSunlitArea(HTS) -=
    9353         2402 :                             state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
    9354              : 
    9355         2402 :                         if (iHour > 0 && TS > 0) {
    9356         1542 :                             state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
    9357         1542 :                                 state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
    9358              :                         }
    9359              : 
    9360         2402 :                         SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
    9361              : 
    9362         2402 :                         if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    9363            0 :                             state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9364              :                         }
    9365              : 
    9366              :                     } else { // General receiving surface totally shaded.
    9367              : 
    9368          319 :                         state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9369              :                     }
    9370              :                 }
    9371              :             }
    9372              : 
    9373              :             // Determine transmittance and absorptances of sunlit window.
    9374        17158 :             if (state.dataConstruction->Construct(K).TransDiff > 0.0) {
    9375              : 
    9376        11878 :                 if (!state.dataSolarShading->CalcSkyDifShading) { // Overlaps calculation is only done for beam solar
    9377              :                     // shading, not for sky diffuse solar shading
    9378              : 
    9379         6982 :                     CalcInteriorSolarOverlaps(state, iHour, NBKS, HTSS, CurSurf, TS);
    9380              :                 }
    9381              :             }
    9382              : 
    9383              :             // Error checking.
    9384        17158 :             SurfArea = s_surf->Surface(SBSNR).NetAreaShadowCalc;
    9385        17158 :             state.dataSolarShading->SurfSunlitArea(HTSS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTSS));
    9386              : 
    9387        17158 :             state.dataSolarShading->SurfSunlitArea(HTSS) = min(state.dataSolarShading->SurfSunlitArea(HTSS), SurfArea);
    9388              : 
    9389              :         } // End of subsurface loop
    9390              :     }
    9391        90268 : }
    9392              : 
    9393         2216 : void SUN3(int const JulianDayOfYear,      // Julian Day Of Year
    9394              :           Real64 &SineOfSolarDeclination, // Sine of Solar Declination
    9395              :           Real64 &EquationOfTime          // Equation of Time (Degrees)
    9396              : )
    9397              : {
    9398              : 
    9399              :     // SUBROUTINE INFORMATION:
    9400              :     //       AUTHOR         Legacy Code
    9401              :     //       DATE WRITTEN
    9402              :     //       MODIFIED       na
    9403              :     //       RE-ENGINEERED  Linda K. Lawrie
    9404              : 
    9405              :     // PURPOSE OF THIS SUBROUTINE:
    9406              :     // This subroutine computes the coefficients for determining
    9407              :     // the solar position.
    9408              : 
    9409              :     // METHODOLOGY EMPLOYED:
    9410              :     // The expressions are based on least-squares fits of data on p.316 of 'Thermal
    9411              :     // Environmental Engineering' by Threlkeld and on p.387 of the ASHRAE Handbook
    9412              :     // of Fundamentals (need date of ASHRAE HOF).
    9413              : 
    9414              :     // REFERENCES:
    9415              :     // BLAST/IBLAST code, original author George Walton
    9416              : 
    9417              :     // Fitted coefficients of Fourier series | Sine of declination coefficients
    9418              :     static constexpr std::array<Real64, 9> SineSolDeclCoef = {
    9419              :         0.00561800, 0.0657911, -0.392779, 0.00064440, -0.00618495, -0.00010101, -0.00007951, -0.00011691, 0.00002096};
    9420              :     // Fitted coefficients of Fourier Series | Equation of Time coefficients
    9421              :     static constexpr std::array<Real64, 9> EqOfTimeCoef = {
    9422              :         0.00021971, -0.122649, 0.00762856, -0.156308, -0.0530028, -0.00388702, -0.00123978, -0.00270502, -0.00167992};
    9423              : 
    9424              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9425              :     Real64 X;     // Day of Year in Radians (Computed from Input JulianDayOfYear)
    9426              :     Real64 CosX;  // COS(X)
    9427              :     Real64 SineX; // SIN(X)
    9428              : 
    9429         2216 :     X = 0.017167 * JulianDayOfYear; // Convert julian date to angle X
    9430              : 
    9431              :     // Calculate sines and cosines of X
    9432         2216 :     SineX = std::sin(X);
    9433         2216 :     CosX = std::cos(X);
    9434              : 
    9435         2216 :     SineOfSolarDeclination = SineSolDeclCoef[0] + SineSolDeclCoef[1] * SineX + SineSolDeclCoef[2] * CosX + SineSolDeclCoef[3] * (SineX * CosX * 2.0) +
    9436         2216 :                              SineSolDeclCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
    9437         2216 :                              SineSolDeclCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
    9438         2216 :                              SineSolDeclCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
    9439         2216 :                              SineSolDeclCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
    9440         2216 :                              SineSolDeclCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
    9441              : 
    9442         2216 :     EquationOfTime = EqOfTimeCoef[0] + EqOfTimeCoef[1] * SineX + EqOfTimeCoef[2] * CosX + EqOfTimeCoef[3] * (SineX * CosX * 2.0) +
    9443         2216 :                      EqOfTimeCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
    9444         2216 :                      EqOfTimeCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
    9445         2216 :                      EqOfTimeCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
    9446         2216 :                      EqOfTimeCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
    9447         2216 :                      EqOfTimeCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
    9448         2216 : }
    9449              : 
    9450        30561 : void SUN4(EnergyPlusData &state,
    9451              :           Real64 const CurrentTime,    // Time to use in shadowing calculations
    9452              :           Real64 const EqOfTime,       // Equation of time for current day
    9453              :           Real64 const SinSolarDeclin, // Sine of the Solar declination (current day)
    9454              :           Real64 const CosSolarDeclin  // Cosine of the Solar declination (current day)
    9455              : )
    9456              : {
    9457              : 
    9458              :     // SUBROUTINE INFORMATION:
    9459              :     //       AUTHOR         Legacy Code
    9460              :     //       DATE WRITTEN
    9461              :     //       MODIFIED       na
    9462              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    9463              : 
    9464              :     // PURPOSE OF THIS SUBROUTINE:
    9465              :     // This subroutine computes solar direction cosines for a given hour.  These
    9466              :     // cosines are used in the shadowing calculations.
    9467              :     // REFERENCES:
    9468              :     // BLAST/IBLAST code, original author George Walton
    9469              : 
    9470              :     Real64 H;       // Hour angle (before noon = +) (in radians)
    9471              :     Real64 HrAngle; // Basic hour angle
    9472              : 
    9473              :     // Compute the hour angle
    9474        30561 :     HrAngle = (15.0 * (12.0 - (CurrentTime + EqOfTime)) + (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
    9475        30561 :     H = HrAngle * Constant::DegToRad;
    9476              : 
    9477              :     // Compute the cosine of the solar zenith angle.
    9478        30561 :     state.dataSolarShading->SUNCOS(3) = SinSolarDeclin * state.dataEnvrn->SinLatitude + CosSolarDeclin * state.dataEnvrn->CosLatitude * std::cos(H);
    9479        30561 :     state.dataSolarShading->SUNCOS(2) = 0.0;
    9480        30561 :     state.dataSolarShading->SUNCOS(1) = 0.0;
    9481              : 
    9482        30561 :     if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) {
    9483        15503 :         return; // Return if sun not above horizon.
    9484              :     }
    9485              : 
    9486              :     // Compute other direction cosines.
    9487        15058 :     state.dataSolarShading->SUNCOS(2) = SinSolarDeclin * state.dataEnvrn->CosLatitude - CosSolarDeclin * state.dataEnvrn->SinLatitude * std::cos(H);
    9488        15058 :     state.dataSolarShading->SUNCOS(1) = CosSolarDeclin * std::sin(H);
    9489              : }
    9490              : 
    9491       249958 : void WindowShadingManager(EnergyPlusData &state)
    9492              : {
    9493              : 
    9494              :     // SUBROUTINE INFORMATION:
    9495              :     //       AUTHOR         Fred Winkelmann
    9496              :     //       DATE WRITTEN   December 1998
    9497              :     //       MODIFIED       November 1999 (FW)
    9498              :     //                      Aug 2001 (FW): change shading control names, change approach
    9499              :     //                       to scheduling and glare control, add movable
    9500              :     //                       insulation controls (mainly for heating reduction)
    9501              :     //                      Dec 2001 (FW): add slat angle control for blinds
    9502              :     //                      Aug 2002 (FW): add four new control types:
    9503              :     //                        OnIfHighOutsideAirTempAndHighSolarOnWindow
    9504              :     //                        OnIfHighOutsideAirTempAndHighHorizontalSolar
    9505              :     //                        OnIfHighZoneAirTempAndHighSolarOnWindow
    9506              :     //                        OnIfHighZoneAirTempAndHighHorizontalSolar
    9507              :     //                      Dec 2002 (FW): add between-glass shade/blind
    9508              :     //                      Mar 2003 (FW): allow GlareControlIsActive = .TRUE. only for daylit zones
    9509              :     //                      Apr 2003 (FW): use SNLoadCoolRate or SNLoadHeatRate only if not first time step
    9510              :     //                                     (fixes problem when used first time thru and not allocated)
    9511              :     //                      May 2006 (RR): add exterior window screen
    9512              :     //                      May 2009 (BG): add EMS actuator override for shade flag and slat angle
    9513              :     //       RE-ENGINEERED  na
    9514              : 
    9515              :     // PURPOSE OF THIS SUBROUTINE:
    9516              :     // For windows with shading, selects the shaded construction
    9517              :     // that is used in the heat balance calculation, and sets
    9518              :     // the window shading flag, which is:
    9519              :     //  -1: if window has no shading device
    9520              :     //   0: if shading device is off
    9521              :     //   1: if interior shade is on
    9522              :     //   2: if glazing is switched to darker state
    9523              :     //   3: if exterior shade is on
    9524              :     //   6: if interior blind is on
    9525              :     //   7: if exterior blind is on
    9526              :     //   8: if between-glass shade is on
    9527              :     //   9: if between-glass blind is on
    9528              :     //  10: window has interior shade that is off but may be triggered on later
    9529              :     //       to control daylight glare
    9530              :     //  20: window has switchable glazing that is unswitched but may be switched later
    9531              :     //       to control daylight glare or daylight illuminance
    9532              :     //  30: window has exterior shade that is off but may be triggered on later
    9533              :     //       to control daylight glare or daylight illuminance
    9534              :     //  60: window has interior blind that is off but may be triggered on later
    9535              :     //       to control daylight glare or daylight illuminance
    9536              :     //  70: window has exterior blind that is off but may be triggered on later
    9537              :     //       to control daylight glare or daylight illuminance
    9538              :     //  80: window has between-glass shade that is off but may be triggered on later
    9539              :     //       to control daylight glare or daylight illuminance
    9540              :     //  90: window has between-glass blind that is off but may be triggered on later
    9541              :     //       to control daylight glare or daylight illuminance
    9542              :     // A "shading device" may be an exterior, interior or between-glass shade or blind,
    9543              :     // or the lower-transmitting (dark) state of switchable glazing (e.g., electrochromic).
    9544              :     // In all cases, the unshaded condition is represented
    9545              :     // by the construction given by window's Surface()%Construction and
    9546              :     // the shaded condition is represented by the construction given by
    9547              :     // the window's Surface()%ShadedConstruction
    9548              :     // REFERENCES:
    9549              :     // na
    9550              : 
    9551              :     int IConst; // Construction
    9552              : 
    9553       249958 :     auto &s_mat = state.dataMaterial;
    9554       249958 :     auto &s_surf = state.dataSurface;
    9555              : 
    9556       586610 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    9557       706907 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    9558       370255 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    9559       370255 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
    9560       370255 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
    9561       458823 :             for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
    9562        88568 :                 auto &surfWin = s_surf->SurfaceWindow(ISurf);
    9563        88568 :                 s_surf->SurfWinExtIntShadePrevTS(ISurf) = s_surf->SurfWinShadingFlag(ISurf);
    9564              : 
    9565        88568 :                 s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::NoShade;
    9566        88568 :                 s_surf->SurfWinFracTimeShadingDeviceOn(ISurf) = 0.0;
    9567        88568 :                 if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::EQL) {
    9568         2369 :                     int EQLNum = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction).EQLConsPtr;
    9569         2369 :                     if (state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr > 0) {
    9570         1473 :                         auto &surfShade = s_surf->surfShades(ISurf);
    9571         1473 :                         if (state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).CNTRL ==
    9572         1473 :                             state.dataWindowEquivalentLayer->lscNONE) {
    9573          507 :                             surfShade.blind.slatAngDeg =
    9574          507 :                                 state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).PHI_DEG;
    9575              :                         } else {
    9576          966 :                             surfShade.blind.slatAngDeg = 0.0;
    9577              :                         }
    9578              :                     }
    9579              :                 }
    9580              : 
    9581              :                 // Initialization of complex fenestration shading device
    9582        88568 :                 if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::BSDF) {
    9583            0 :                     auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
    9584            0 :                     int TotLayers = construction.TotLayers;
    9585            0 :                     for (int Lay = 1; Lay <= TotLayers; ++Lay) {
    9586            0 :                         const int LayPtr = construction.LayerPoint(Lay);
    9587            0 :                         auto const *material = s_mat->materials(LayPtr);
    9588            0 :                         const bool isShading = material->group == Material::Group::ComplexShade;
    9589            0 :                         if (isShading && Lay == 1) {
    9590            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShade;
    9591              :                         }
    9592            0 :                         if (isShading && Lay == TotLayers) {
    9593            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShade;
    9594              :                         }
    9595              :                     }
    9596              : 
    9597            0 :                     if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntShade) {
    9598            0 :                         auto &surfShade = s_surf->surfShades(ISurf);
    9599            0 :                         auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
    9600            0 :                         const int TotLay = construction.TotLayers;
    9601            0 :                         int ShadingLayerPtr = construction.LayerPoint(TotLay);
    9602              : 
    9603            0 :                         auto const *matComplexShade = dynamic_cast<Material::MaterialComplexShade *>(s_mat->materials(ShadingLayerPtr));
    9604            0 :                         Real64 TauShadeIR = matComplexShade->TransThermal;
    9605            0 :                         Real64 EpsShadeIR = matComplexShade->BackEmissivity;
    9606            0 :                         Real64 RhoShadeIR = max(0.0, 1.0 - TauShadeIR - EpsShadeIR);
    9607              :                         // Get properties of glass next to inside shading layer
    9608            0 :                         int GlassLayPtr = construction.LayerPoint(TotLay - 2);
    9609            0 :                         Real64 EpsGlassIR = s_mat->materials(GlassLayPtr)->AbsorpThermalBack;
    9610            0 :                         Real64 RhoGlassIR = 1 - EpsGlassIR;
    9611              : 
    9612            0 :                         surfShade.effShadeEmi = EpsShadeIR * (1.0 + RhoGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR));
    9613            0 :                         surfShade.effGlassEmi = EpsGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR);
    9614              :                     }
    9615              :                 }
    9616              : 
    9617        88568 :                 if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) {
    9618            0 :                     continue;
    9619              :                 }
    9620        88568 :                 if (!s_surf->Surface(ISurf).HasShadeControl) {
    9621        56212 :                     continue;
    9622              :                 } else {
    9623              :                     //
    9624              :                 }
    9625              : 
    9626              :                 // Initialize switching factor (applicable only to switchable glazing) to unswitched
    9627        32356 :                 s_surf->SurfWinSwitchingFactor(ISurf) = 0.0;
    9628              : 
    9629        32356 :                 IConst = s_surf->Surface(ISurf).Construction;
    9630              :                 // Vis trans at normal incidence of unswitched glass. Counting the GlazedFrac
    9631        32356 :                 if (IConst > 0) {
    9632        32352 :                     s_surf->SurfWinVisTransSelected(ISurf) =
    9633        32352 :                         Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
    9634              :                 }
    9635              : 
    9636              :                 // Window has shading control
    9637              :                 // select the active window shading control and corresponding constructions
    9638        32356 :                 size_t indexWindowShadingControl = selectActiveWindowShadingControlIndex(state, ISurf);
    9639        64712 :                 if (!s_surf->Surface(ISurf).windowShadingControlList.empty() &&
    9640        32356 :                     indexWindowShadingControl <= s_surf->Surface(ISurf).windowShadingControlList.size() - 1) {
    9641        32356 :                     s_surf->Surface(ISurf).activeWindowShadingControl = s_surf->Surface(ISurf).windowShadingControlList[indexWindowShadingControl];
    9642              :                 }
    9643        32356 :                 s_surf->Surface(ISurf).activeShadedConstructionPrev = s_surf->Surface(ISurf).activeShadedConstruction;
    9644        64708 :                 if (!s_surf->Surface(ISurf).shadedConstructionList.empty() &&
    9645        32352 :                     indexWindowShadingControl <= s_surf->Surface(ISurf).shadedConstructionList.size() - 1) {
    9646        32352 :                     s_surf->Surface(ISurf).activeShadedConstruction = s_surf->Surface(ISurf).shadedConstructionList[indexWindowShadingControl];
    9647              :                 }
    9648        32356 :                 s_surf->SurfWinActiveShadedConstruction(ISurf) = s_surf->Surface(ISurf).activeShadedConstruction;
    9649        32356 :                 if (!s_surf->Surface(ISurf).shadedStormWinConstructionList.empty() &&
    9650            0 :                     indexWindowShadingControl <= s_surf->Surface(ISurf).shadedStormWinConstructionList.size() - 1) {
    9651            0 :                     if (s_surf->SurfWinStormWinFlag(ISurf) == 1) {
    9652            0 :                         s_surf->SurfWinActiveShadedConstruction(ISurf) =
    9653            0 :                             s_surf->Surface(ISurf).shadedStormWinConstructionList[indexWindowShadingControl];
    9654              :                     }
    9655              :                 }
    9656              : 
    9657        32356 :                 int IShadingCtrl = s_surf->Surface(ISurf).activeWindowShadingControl;
    9658        32356 :                 int IZone = s_surf->Surface(ISurf).Zone;
    9659              :                 // Setpoint for shading
    9660        32356 :                 Real64 SetPoint = s_surf->WindowShadingControl(IShadingCtrl).SetPoint;   // Control setpoint
    9661        32356 :                 Real64 SetPoint2 = s_surf->WindowShadingControl(IShadingCtrl).SetPoint2; // Second control setpoint
    9662              : 
    9663        32356 :                 bool SchedAllowsControl = true; // True if control schedule is not specified or is specified and schedule value = 1
    9664        32356 :                 auto const *sched = s_surf->WindowShadingControl(IShadingCtrl).sched;
    9665        32356 :                 if (sched != nullptr) {
    9666        32352 :                     if (s_surf->WindowShadingControl(IShadingCtrl).ShadingControlIsScheduled && sched->getCurrentVal() <= 0.0) {
    9667        32352 :                         SchedAllowsControl = false;
    9668              :                     }
    9669              :                 }
    9670              : 
    9671        32356 :                 Real64 GlareControlIsActive = (state.dataDayltg->ZoneDaylight(IZone).totRefPts > 0 && state.dataEnvrn->SunIsUp &&
    9672            0 :                                                s_surf->WindowShadingControl(IShadingCtrl).GlareControlIsActive); // True if glare control is active
    9673              : 
    9674        32356 :                 Real64 SolarOnWindow = 0.0;     // Direct plus diffuse solar intensity on window (W/m2)
    9675        32356 :                 Real64 BeamSolarOnWindow = 0.0; // Direct solar intensity on window (W/m2)
    9676        32356 :                 Real64 HorizSolar = 0.0;        // Horizontal direct plus diffuse solar intensity
    9677        32356 :                 if (state.dataEnvrn->SunIsUp) {
    9678        16354 :                     Real64 SkySolarOnWindow = state.dataSolarShading->SurfAnisoSkyMult(ISurf) *
    9679        16354 :                                               state.dataEnvrn->DifSolarRad; // Sky diffuse solar intensity on window (W/m2)
    9680        16354 :                     BeamSolarOnWindow = state.dataEnvrn->BeamSolarRad *
    9681        16354 :                                         state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf) *
    9682        16354 :                                         state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf);
    9683        16354 :                     SolarOnWindow = BeamSolarOnWindow + SkySolarOnWindow + state.dataEnvrn->GndSolarRad * s_surf->Surface(ISurf).ViewFactorGround;
    9684        16354 :                     HorizSolar = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3) + state.dataEnvrn->DifSolarRad;
    9685              :                 }
    9686              : 
    9687              :                 // Determine whether to deploy shading depending on type of control
    9688        32356 :                 auto &thisIZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(IZone);
    9689              : 
    9690        32356 :                 bool shadingOn = false;
    9691        32356 :                 bool shadingOffButGlareControlOn = false;
    9692        32356 :                 switch (s_surf->WindowShadingControl(IShadingCtrl).shadingControlType) {
    9693            0 :                 case WindowShadingControlType::AlwaysOn: // 'ALWAYSON'
    9694            0 :                     shadingOn = true;
    9695            0 :                     break;
    9696            0 :                 case WindowShadingControlType::AlwaysOff: // 'ALWAYSOFF'
    9697            0 :                     break;
    9698        32352 :                 case WindowShadingControlType::OnIfScheduled: // 'ONIFSCHEDULEALLOWS'
    9699        32352 :                     if (SchedAllowsControl) {
    9700            0 :                         shadingOn = true;
    9701              :                     }
    9702        32352 :                     break;
    9703            0 :                 case WindowShadingControlType::HiSolar: // 'ONIFHIGHSOLARONWINDOW'
    9704              :                     // ! Direct plus diffuse solar intensity on window
    9705            0 :                     if (state.dataEnvrn->SunIsUp) {
    9706            0 :                         if (SolarOnWindow > SetPoint && SchedAllowsControl) {
    9707            0 :                             shadingOn = true;
    9708            0 :                         } else if (GlareControlIsActive) {
    9709            0 :                             shadingOffButGlareControlOn = true;
    9710              :                         }
    9711              :                     }
    9712            0 :                     break;
    9713              : 
    9714            0 :                 case WindowShadingControlType::HiHorzSolar: // 'ONIFHIGHHORIZONTALSOLAR'  ! Direct plus diffuse exterior horizontal solar intensity
    9715            0 :                     if (state.dataEnvrn->SunIsUp) {
    9716            0 :                         if (HorizSolar > SetPoint && SchedAllowsControl) {
    9717            0 :                             shadingOn = true;
    9718            0 :                         } else if (GlareControlIsActive) {
    9719            0 :                             shadingOffButGlareControlOn = true;
    9720              :                         }
    9721              :                     }
    9722            0 :                     break;
    9723              : 
    9724            0 :                 case WindowShadingControlType::HiOutAirTemp: // 'OnIfHighOutdoorAirTemperature'
    9725            0 :                     if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SchedAllowsControl) {
    9726            0 :                         shadingOn = true;
    9727            0 :                     } else if (GlareControlIsActive) {
    9728            0 :                         shadingOffButGlareControlOn = true;
    9729              :                     }
    9730            0 :                     break;
    9731              : 
    9732            0 :                 case WindowShadingControlType::HiZoneAirTemp: // 'OnIfHighZoneAirTemperature'  ! Previous time step zone air temperature
    9733            0 :                     if (thisIZoneHB.MAT > SetPoint && SchedAllowsControl) {
    9734            0 :                         shadingOn = true;
    9735            0 :                     } else if (GlareControlIsActive) {
    9736            0 :                         shadingOffButGlareControlOn = true;
    9737              :                     }
    9738            0 :                     break;
    9739              : 
    9740            0 :                 case WindowShadingControlType::OnHiOutTemp_HiSolarWindow: // 'OnIfHighOutdoorAirTempAndHighSolarOnWindow'  ! Outside air temp and
    9741              :                                                                           // solar on window
    9742            0 :                     if (state.dataEnvrn->SunIsUp) {
    9743            0 :                         if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
    9744            0 :                             shadingOn = true;
    9745            0 :                         } else if (GlareControlIsActive) {
    9746            0 :                             shadingOffButGlareControlOn = true;
    9747              :                         }
    9748              :                     }
    9749            0 :                     break;
    9750              : 
    9751            0 :                 case WindowShadingControlType::OnHiOutTemp_HiHorzSolar: // 'OnIfHighOutdoorAirTempAndHighHorizontalSolar'  ! Outside air temp and
    9752              :                                                                         // horizontal solar
    9753            0 :                     if (state.dataEnvrn->SunIsUp) {
    9754            0 :                         if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
    9755            0 :                             shadingOn = true;
    9756            0 :                         } else if (GlareControlIsActive) {
    9757            0 :                             shadingOffButGlareControlOn = true;
    9758              :                         }
    9759              :                     }
    9760            0 :                     break;
    9761              : 
    9762            0 :                 case WindowShadingControlType::OnHiZoneTemp_HiSolarWindow: // 'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW'  ! Zone air temp and solar on
    9763              :                                                                            // window
    9764            0 :                     if (state.dataEnvrn->SunIsUp) {
    9765            0 :                         if (thisIZoneHB.MAT > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
    9766            0 :                             shadingOn = true;
    9767            0 :                         } else if (GlareControlIsActive) {
    9768            0 :                             shadingOffButGlareControlOn = true;
    9769              :                         }
    9770              :                     }
    9771            0 :                     break;
    9772              : 
    9773            0 :                 case WindowShadingControlType::OnHiZoneTemp_HiHorzSolar: // 'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR'  ! Zone air temp and
    9774              :                                                                          // horizontal solar
    9775            0 :                     if (state.dataEnvrn->SunIsUp) {
    9776            0 :                         if (thisIZoneHB.MAT > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
    9777            0 :                             shadingOn = true;
    9778            0 :                         } else if (GlareControlIsActive) {
    9779            0 :                             shadingOffButGlareControlOn = true;
    9780              :                         }
    9781              :                     }
    9782            0 :                     break;
    9783              : 
    9784            0 :                 case WindowShadingControlType::HiZoneCooling:
    9785              :                     // 'ONIFHIGHZONECOOLING'  ! Previous time step zone sensible cooling rate [W]
    9786              :                     // In the following, the check on BeginSimFlag is needed since SNLoadCoolRate (and SNLoadHeatRate,
    9787              :                     // used in other CASEs) are not allocated at this point for the first time step of the simulation.
    9788            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9789            0 :                         if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > SetPoint && SchedAllowsControl) {
    9790            0 :                             shadingOn = true;
    9791            0 :                         } else if (GlareControlIsActive) {
    9792            0 :                             shadingOffButGlareControlOn = true;
    9793              :                         }
    9794              :                     }
    9795            0 :                     break;
    9796              : 
    9797            0 :                 case WindowShadingControlType::HiGlare:
    9798              :                     // 'ONIFHIGHGLARE'  ! Daylight glare index at first reference point in the zone.
    9799              :                     // This type of shading control is done in DayltgInteriorIllum. Glare control is not affected
    9800              :                     // by control schedule.
    9801            0 :                     if (state.dataEnvrn->SunIsUp) {
    9802            0 :                         shadingOffButGlareControlOn = true;
    9803              :                     }
    9804            0 :                     break;
    9805              : 
    9806            0 :                 case WindowShadingControlType::MeetDaylIlumSetp:
    9807              :                     // 'MEETDAYLIGHTILLUMINANCESETPOINT')  !  Daylight illuminance test is done in DayltgInteriorIllum
    9808              :                     // Only switchable glazing does daylight illuminance control
    9809            0 :                     if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9810            0 :                         shadingOffButGlareControlOn = true;
    9811              :                     }
    9812            0 :                     break;
    9813              : 
    9814            1 :                 case WindowShadingControlType::HiSolar_HiLumin_OffMidNight:
    9815              :                     // 'OnIfHighSolarOrHighLuminanceTillMidnight'
    9816              :                     // if shade is already on, then keep it on until midnight, otherwise check thresholds
    9817            1 :                     if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
    9818            0 :                         shadingOn = true;
    9819            1 :                     } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9820            1 :                         if (SolarOnWindow > SetPoint) {
    9821            0 :                             shadingOn = true;
    9822              :                         } else {
    9823              :                             // pass to DayltgInteriorIllum to check for luminance
    9824            1 :                             shadingOn = false;
    9825            1 :                             shadingOffButGlareControlOn = true;
    9826              :                         }
    9827              :                     }
    9828              :                     // if it is the beginning of the day, then shades off
    9829            1 :                     if (state.dataGlobal->BeginDayFlag) {
    9830            0 :                         shadingOn = false;
    9831            0 :                         shadingOffButGlareControlOn = false;
    9832              :                     }
    9833            1 :                     break;
    9834              : 
    9835            0 :                 case WindowShadingControlType::HiSolar_HiLumin_OffSunset:
    9836              :                     // 'OnIfHighSolarOrHighLuminanceTillSunset'
    9837              :                     // if shade is already on, then keep it on until sunset, otherwise check thresholds
    9838            0 :                     if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
    9839            0 :                         shadingOn = true;
    9840            0 :                     } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9841            0 :                         if (SolarOnWindow > SetPoint) {
    9842            0 :                             shadingOn = true;
    9843              :                         } else {
    9844              :                             // pass to DayltgInteriorIllum to check for luminance
    9845            0 :                             shadingOn = false;
    9846            0 :                             shadingOffButGlareControlOn = true;
    9847              :                         }
    9848              :                     }
    9849              :                     // if sunset, then shades off
    9850            0 :                     if (!state.dataEnvrn->SunIsUp) {
    9851            0 :                         shadingOn = false;
    9852            0 :                         shadingOffButGlareControlOn = false;
    9853              :                     }
    9854            0 :                     break;
    9855              : 
    9856            1 :                 case WindowShadingControlType::HiSolar_HiLumin_OffNextMorning:
    9857              :                     // 'OnIfHighSolarOrHighLuminanceTillNextMorning'
    9858              :                     // if shade is already on, then keep it on until next day when sun is up, otherwise check thresholds
    9859            1 :                     if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
    9860            0 :                         shadingOn = true;
    9861            1 :                     } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9862            1 :                         if (SolarOnWindow > SetPoint) {
    9863            1 :                             shadingOn = true;
    9864              :                         } else {
    9865              :                             // pass to DayltgInteriorIllum to check for luminance
    9866            0 :                             shadingOn = false;
    9867            0 :                             shadingOffButGlareControlOn = true;
    9868              :                         }
    9869              :                     }
    9870              :                     // if next morning (identified by sun is not up in previous time step and is up now), then shades off
    9871            1 :                     if (!state.dataEnvrn->SunIsUpPrevTS && state.dataEnvrn->SunIsUp) {
    9872            0 :                         shadingOn = false;
    9873            0 :                         shadingOffButGlareControlOn = false;
    9874              :                     }
    9875            1 :                     break;
    9876              : 
    9877            0 :                 case WindowShadingControlType::OnNightLoOutTemp_OffDay: // 'OnNightIfLowOutdoorTempAndOffDay'
    9878            0 :                     if (!state.dataEnvrn->SunIsUp && s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
    9879            0 :                         shadingOn = true;
    9880            0 :                     } else if (GlareControlIsActive) {
    9881            0 :                         shadingOffButGlareControlOn = true;
    9882              :                     }
    9883            0 :                     break;
    9884              : 
    9885            0 :                 case WindowShadingControlType::OnNightLoInTemp_OffDay: // 'OnNightIfLowInsideTempAndOffDay')
    9886            0 :                     if (!state.dataEnvrn->SunIsUp && thisIZoneHB.MAT < SetPoint && SchedAllowsControl) {
    9887            0 :                         shadingOn = true;
    9888            0 :                     } else if (GlareControlIsActive) {
    9889            0 :                         shadingOffButGlareControlOn = true;
    9890              :                     }
    9891            0 :                     break;
    9892              : 
    9893            0 :                 case WindowShadingControlType::OnNightIfHeating_OffDay: // 'OnNightIfHeatingAndOffDay'
    9894            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9895            0 :                         if (!state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint &&
    9896              :                             SchedAllowsControl) {
    9897            0 :                             shadingOn = true;
    9898            0 :                         } else if (GlareControlIsActive) {
    9899            0 :                             shadingOffButGlareControlOn = true;
    9900              :                         }
    9901              :                     }
    9902            0 :                     break;
    9903              : 
    9904            0 :                 case WindowShadingControlType::OnNightLoOutTemp_OnDayCooling: // 'OnNightIfLowOutdoorTempAndOnDayIfCooling'
    9905            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9906            0 :                         if (!state.dataEnvrn->SunIsUp) { // Night
    9907            0 :                             if (s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
    9908            0 :                                 shadingOn = true;
    9909              :                             }
    9910              :                         } else { // Day
    9911            0 :                             if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
    9912            0 :                                 shadingOn = true;
    9913            0 :                             } else if (GlareControlIsActive) {
    9914            0 :                                 shadingOffButGlareControlOn = true;
    9915              :                             }
    9916              :                         }
    9917              :                     }
    9918            0 :                     break;
    9919              : 
    9920            0 :                 case WindowShadingControlType::OnNightIfHeating_OnDayCooling: // 'OnNightIfHeatingAndOnDayIfCooling'
    9921            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9922            0 :                         if (!state.dataEnvrn->SunIsUp) { // Night
    9923            0 :                             if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint && SchedAllowsControl) {
    9924            0 :                                 shadingOn = true;
    9925              :                             }
    9926              :                         } else { // Day
    9927            0 :                             if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
    9928            0 :                                 shadingOn = true;
    9929            0 :                             } else if (GlareControlIsActive) {
    9930            0 :                                 shadingOffButGlareControlOn = true;
    9931              :                             }
    9932              :                         }
    9933              :                     }
    9934            0 :                     break;
    9935              : 
    9936            0 :                 case WindowShadingControlType::OffNight_OnDay_HiSolarWindow: // 'OffNightAndOnDayIfCoolingAndHighSolarOnWindow'
    9937            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9938            0 :                         if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
    9939              :                             SchedAllowsControl) {
    9940            0 :                             if (SolarOnWindow > SetPoint) {
    9941            0 :                                 shadingOn = true;
    9942              :                             }
    9943            0 :                         } else if (GlareControlIsActive) {
    9944            0 :                             shadingOffButGlareControlOn = true;
    9945              :                         }
    9946              :                     }
    9947            0 :                     break;
    9948              : 
    9949            0 :                 case WindowShadingControlType::OnNight_OnDay_HiSolarWindow: // 'OnNightAndOnDayIfCoolingAndHighSolarOnWindow'
    9950            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9951            0 :                         if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
    9952              :                             SchedAllowsControl) {
    9953            0 :                             if (SolarOnWindow > SetPoint) {
    9954            0 :                                 shadingOn = true;
    9955              :                             }
    9956            0 :                         } else if (!state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9957            0 :                             shadingOn = true;
    9958            0 :                         } else if (GlareControlIsActive) {
    9959            0 :                             shadingOffButGlareControlOn = true;
    9960              :                         }
    9961              :                     }
    9962            0 :                     break;
    9963            2 :                 default:
    9964            2 :                     ShowWarningError(state, format("Invalid Selection of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
    9965              :                 }
    9966              : 
    9967        32356 :                 WinShadingType ShType = s_surf->WindowShadingControl(IShadingCtrl).ShadingType;
    9968              : 
    9969        32356 :                 s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ShadeOff; // Initialize shading flag to off
    9970              : 
    9971        32356 :                 if (IS_SHADED(ShType)) {
    9972        32355 :                     if (shadingOn) {
    9973            1 :                         s_surf->SurfWinShadingFlag(ISurf) = ShType;
    9974        32354 :                     } else if (shadingOffButGlareControlOn) {
    9975            1 :                         if (ShType == WinShadingType::SwitchableGlazing) {
    9976            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::GlassConditionallyLightened;
    9977            1 :                         } else if (ShType == WinShadingType::IntShade) {
    9978            1 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShadeConditionallyOff;
    9979            0 :                         } else if (ShType == WinShadingType::ExtShade) {
    9980            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShadeConditionallyOff;
    9981            0 :                         } else if (ShType == WinShadingType::IntBlind) {
    9982            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntBlindConditionallyOff;
    9983            0 :                         } else if (ShType == WinShadingType::ExtBlind) {
    9984            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtBlindConditionallyOff;
    9985            0 :                         } else if (ShType == WinShadingType::BGShade) {
    9986            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGShadeConditionallyOff;
    9987            0 :                         } else if (ShType == WinShadingType::BGBlind) {
    9988            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGBlindConditionallyOff;
    9989              :                         }
    9990              :                     }
    9991              :                 }
    9992              : 
    9993              :                 // Set switching factor to fully switched if ShadingFlag = 2
    9994        32356 :                 if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::SwitchableGlazing) {
    9995            0 :                     s_surf->SurfWinSwitchingFactor(ISurf) = 1.0;
    9996              : 
    9997              :                     // Added TH 1/20/2010
    9998              :                     // Vis trans at normal incidence of fully switched glass
    9999            0 :                     IConst = s_surf->Surface(ISurf).activeShadedConstruction;
   10000            0 :                     s_surf->SurfWinVisTransSelected(ISurf) =
   10001            0 :                         Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
   10002              :                 }
   10003              : 
   10004              :                 // Slat angle control for blinds
   10005        32356 :                 auto &surfShade = s_surf->surfShades(ISurf);
   10006        32356 :                 surfShade.blind.slatAng = 0.0;
   10007        32356 :                 surfShade.blind.slatAngDeg = 0.0;
   10008        32356 :                 surfShade.blind.slatBlockBeam = false;
   10009        64712 :                 if (ANY_BLIND(s_surf->SurfWinShadingFlag(ISurf)) || s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntBlindConditionallyOff ||
   10010        97068 :                     s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtBlindConditionallyOff ||
   10011        32356 :                     s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::BGBlindConditionallyOff) {
   10012              :                     // Blind in place or may be in place due to glare control
   10013            0 :                     if (surfShade.blind.matNum > 0) {
   10014            0 :                         auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
   10015            0 :                         assert(matBlind != nullptr);
   10016            0 :                         Real64 InputSlatAngle = matBlind->SlatAngle * Constant::DegToRad; // Slat angle of associated Material:WindowBlind (rad)
   10017              :                         Real64 ThetaBase;                                                 // Intermediate slat angle variable (rad)
   10018              :                         Real64 ThetaBlock1;                                               // Slat angles that just block beam solar (rad)
   10019              :                         Real64 ThetaBlock2;
   10020              : 
   10021            0 :                         Real64 ProfAng = surfShade.blind.profAng =
   10022            0 :                             Dayltg::ProfileAngle(state, ISurf, state.dataEnvrn->SOLCOS, matBlind->SlatOrientation);
   10023              : 
   10024            0 :                         if (ProfAng > Constant::PiOvr2 || ProfAng < -Constant::PiOvr2) {
   10025            0 :                             ProfAng = min(max(ProfAng, -Constant::PiOvr2), Constant::PiOvr2);
   10026              :                         }
   10027            0 :                         surfShade.blind.profAngIdxLo = int((ProfAng + Constant::PiOvr2) / Material::dProfAng) + 1;
   10028            0 :                         surfShade.blind.profAngIdxHi = std::min(Material::MaxProfAngs, surfShade.blind.profAngIdxLo + 1);
   10029              : 
   10030            0 :                         surfShade.blind.profAngInterpFac =
   10031            0 :                             (ProfAng + Constant::PiOvr2 - (surfShade.blind.profAngIdxLo - 1) * Material::dProfAng) / Material::dProfAng;
   10032              : 
   10033            0 :                         if (matBlind->SlatWidth > matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
   10034            0 :                             ProfAng = surfShade.blind.profAng;
   10035            0 :                             Real64 ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
   10036              :                             // There are two solutions for the slat angle that just blocks beam radiation
   10037            0 :                             ThetaBlock1 = ProfAng + ThetaBase;
   10038            0 :                             ThetaBlock2 = ProfAng + Constant::Pi - ThetaBase;
   10039            0 :                             state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
   10040            0 :                             state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
   10041            0 :                             state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
   10042            0 :                             state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
   10043              :                         }
   10044              : 
   10045              :                         // TH 5/20/2010, CR 8064: Slat Width <= Slat Separation
   10046            0 :                         if (matBlind->SlatWidth <= matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
   10047            0 :                             if (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl == SlatAngleControl::BlockBeamSolar) {
   10048            0 :                                 ProfAng = surfShade.blind.profAng;
   10049            0 :                                 if (std::abs(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth) <= 1.0) {
   10050              :                                     // set to block 100% of beam solar, not necessarily to block maximum solar (beam + diffuse)
   10051            0 :                                     ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
   10052            0 :                                     surfShade.blind.slatBlockBeam = true;
   10053              :                                 } else {
   10054              :                                     // cannot block 100% of beam solar, turn slats to be perpendicular to sun beam to block maximal beam solar
   10055            0 :                                     ThetaBase = 0.0;
   10056              :                                 }
   10057              : 
   10058              :                                 // There are two solutions for the slat angle that just blocks beam radiation
   10059            0 :                                 ThetaBlock1 = ProfAng + ThetaBase;
   10060            0 :                                 ThetaBlock2 = ProfAng - ThetaBase + Constant::Pi;
   10061              : 
   10062            0 :                                 state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
   10063            0 :                                 state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
   10064            0 :                                 state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
   10065            0 :                                 state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
   10066              :                             }
   10067              :                         }
   10068              : 
   10069              :                         //
   10070            0 :                         Real64 slatAng = 0.0;
   10071            0 :                         bool slatBlockBeam = false;
   10072            0 :                         switch (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl) {
   10073              : 
   10074            0 :                         case SlatAngleControl::Fixed: { // 'FIXEDSLATANGLE'
   10075            0 :                             slatAng = InputSlatAngle;
   10076              : 
   10077            0 :                             if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
   10078            0 :                                 (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0)) {
   10079            0 :                                 slatBlockBeam = true;
   10080              :                             }
   10081            0 :                         } break;
   10082              : 
   10083            0 :                         case SlatAngleControl::Scheduled: { // 'SCHEDULEDSLATANGLE'
   10084            0 :                             slatAng = s_surf->WindowShadingControl(IShadingCtrl).slatAngleSched->getCurrentVal();
   10085            0 :                             slatAng = max(matBlind->MinSlatAngle, min(slatAng, matBlind->MaxSlatAngle)) * Constant::DegToRad;
   10086              : 
   10087            0 :                             if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
   10088            0 :                                 (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0)) {
   10089            0 :                                 slatBlockBeam = true;
   10090              :                             }
   10091            0 :                         } break;
   10092              : 
   10093            0 :                         case SlatAngleControl::BlockBeamSolar: { // 'BLOCKBEAMSOLAR'
   10094            0 :                             if (BeamSolarOnWindow > 0.0) {
   10095            0 :                                 if (matBlind->SlatSeparation >= matBlind->SlatWidth) {
   10096              :                                     // TH 5/20/2010. CR 8064.
   10097              :                                     // The following line of code assumes slats are always vertical/closed to minimize solar penetration
   10098              :                                     // The slat angle can however change if the only goal is to block maximum amount of direct beam solar
   10099              :                                     // SurfaceWindow(ISurf)%SlatAngThisTS = 0.0  ! Allows beam penetration but minimizes it
   10100              : 
   10101            0 :                                     if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
   10102            0 :                                         state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
   10103            0 :                                         slatAng = state.dataSolarShading->ThetaSmall;
   10104            0 :                                     } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
   10105            0 :                                                state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
   10106            0 :                                         slatAng = state.dataSolarShading->ThetaBig;
   10107            0 :                                     } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
   10108            0 :                                                state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
   10109            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
   10110            0 :                                     } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
   10111            0 :                                                state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
   10112            0 :                                         slatAng = state.dataSolarShading->ThetaMax;
   10113              :                                     } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
   10114            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
   10115              :                                     }
   10116              : 
   10117              :                                 } else { // Usual case -- slat width greater than slat separation
   10118            0 :                                     if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
   10119            0 :                                         state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
   10120            0 :                                         slatAng = state.dataSolarShading->ThetaSmall;
   10121            0 :                                         slatBlockBeam = true;
   10122            0 :                                     } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
   10123            0 :                                                state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
   10124            0 :                                         slatAng = state.dataSolarShading->ThetaBig;
   10125            0 :                                         slatBlockBeam = true;
   10126            0 :                                     } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
   10127            0 :                                                state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
   10128            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
   10129            0 :                                         slatBlockBeam = true;
   10130            0 :                                     } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
   10131            0 :                                                state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
   10132            0 :                                         slatAng = state.dataSolarShading->ThetaMax;
   10133            0 :                                         slatBlockBeam = true;
   10134              :                                     } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
   10135            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
   10136              :                                     }
   10137              :                                 }
   10138              :                             } else {
   10139            0 :                                 slatAng = InputSlatAngle;
   10140              :                             }
   10141            0 :                         } break;
   10142            0 :                         default:
   10143            0 :                             break;
   10144              :                         } // switch (slatAngControl)
   10145              : 
   10146            0 :                         if (surfShade.blind.slatAngDegEMSon) {
   10147            0 :                             slatAng = Constant::DegToRad * surfShade.blind.slatAngDegEMSValue;
   10148              :                         }
   10149              : 
   10150              :                         // Slat angle is changing, need to recalculate stored values
   10151            0 :                         if (slatAng != surfShade.blind.slatAng) {
   10152            0 :                             surfShade.blind.slatAng = slatAng;
   10153            0 :                             surfShade.blind.slatAngDeg = surfShade.blind.slatAng * Constant::RadToDeg;
   10154              : 
   10155            0 :                             Material::GetSlatIndicesInterpFac(surfShade.blind.slatAng,
   10156            0 :                                                               surfShade.blind.slatAngIdxLo,
   10157            0 :                                                               surfShade.blind.slatAngIdxHi,
   10158            0 :                                                               surfShade.blind.slatAngInterpFac);
   10159            0 :                             surfShade.blind.TAR.interpSlatAng(matBlind->TARs[surfShade.blind.slatAngIdxLo],
   10160            0 :                                                               matBlind->TARs[surfShade.blind.slatAngIdxHi],
   10161              :                                                               surfShade.blind.slatAngInterpFac);
   10162              : 
   10163            0 :                             Real64 TauShIR = surfShade.blind.TAR.IR.Ft.Tra;
   10164            0 :                             Real64 EpsShIR = surfShade.blind.TAR.IR.Bk.Emi;
   10165            0 :                             Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
   10166              : 
   10167            0 :                             surfShade.effShadeEmi = EpsShIR * (1.0 + surfShade.glass.rhoIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR));
   10168            0 :                             surfShade.effGlassEmi = surfShade.glass.epsIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR);
   10169              :                         }
   10170              : 
   10171            0 :                         surfShade.blind.slatBlockBeam = slatBlockBeam;
   10172              : 
   10173              :                         // Air flow permeability for calculation of convective air flow between blind and glass
   10174            0 :                         Real64 PermeabilityA = std::sin(surfShade.blind.slatAng) - matBlind->SlatThickness / matBlind->SlatSeparation;
   10175            0 :                         Real64 PermeabilityB = 1.0 - (std::abs(matBlind->SlatWidth * std::cos(surfShade.blind.slatAng)) +
   10176            0 :                                                       matBlind->SlatThickness * std::sin(surfShade.blind.slatAng)) /
   10177            0 :                                                          matBlind->SlatSeparation;
   10178            0 :                         surfShade.blind.airFlowPermeability = min(1.0, max(0.0, PermeabilityA, PermeabilityB));
   10179            0 :                         surfShade.blind.bmBmTrans = matBlind->BeamBeamTrans(surfShade.blind.profAng, surfShade.blind.slatAng);
   10180              :                     }
   10181              :                 } // End of check if interior or exterior or between glass blind in place
   10182              : 
   10183              :                 // AR: don't need to do this anymore I don't think
   10184              :                 // CALL CalcScreenTransmittance to initialized all screens prior to HB calc's
   10185              :                 // if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtScreen && state.dataEnvrn->SunIsUp) {
   10186              :                 //    CalcScreenTransmittance(state, ISurf);
   10187              :                 // }
   10188              : 
   10189              :                 // EMS Actuator Point: override setting if ems flag on
   10190        32356 :                 if (s_surf->SurfWinShadingFlagEMSOn(ISurf)) {
   10191            1 :                     WinShadingType SurfWinShadingFlagEMS = findValueInEnumeration(s_surf->SurfWinShadingFlagEMSValue(ISurf));
   10192            1 :                     if (SurfWinShadingFlagEMS != WinShadingType::Invalid) {
   10193            1 :                         s_surf->SurfWinShadingFlag(ISurf) = SurfWinShadingFlagEMS;
   10194              :                     } else {
   10195            0 :                         ShowWarningError(state,
   10196            0 :                                          format("Invalid EMS value of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
   10197              :                     }
   10198              :                 }
   10199              :             } // End of surface loop
   10200       336652 :         }
   10201              :     }
   10202       249958 : }
   10203              : 
   10204       249956 : void CheckGlazingShadingStatusChange(EnergyPlusData &state)
   10205              : {
   10206       249956 :     auto &s_surf = state.dataSurface;
   10207       249956 :     if (state.dataGlobal->BeginSimFlag) {
   10208          112 :         if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() && state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
   10209            0 :             state.dataHeatBal->EnclRadAlwaysReCalc = true;
   10210              :         } else {
   10211          244 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
   10212          281 :                 for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
   10213          149 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
   10214          934 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
   10215          791 :                         auto &surf = s_surf->Surface(SurfNum);
   10216         1582 :                         if (state.dataConstruction->Construct(surf.Construction).isTCWindow ||
   10217          791 :                             state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
   10218            6 :                             state.dataHeatBal->EnclRadAlwaysReCalc = true;
   10219            6 :                             break;
   10220              :                         }
   10221              :                     }
   10222          132 :                 }
   10223              :             }
   10224              :         }
   10225          112 :         if (state.dataHeatBal->EnclRadAlwaysReCalc) {
   10226           12 :             for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
   10227            6 :                 state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
   10228              :             }
   10229           12 :             for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
   10230            6 :                 state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
   10231              :             }
   10232              :         }
   10233              :     }
   10234       249956 :     if (state.dataHeatBal->EnclRadAlwaysReCalc) {
   10235         2368 :         return;
   10236              :     }
   10237              : 
   10238       247588 :     if (state.dataGlobal->BeginEnvrnFlag || state.dataGlobal->AnyConstrOverridesInModel || state.dataGlobal->AnySurfPropOverridesInModel) {
   10239        15397 :         for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
   10240         7818 :             state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
   10241              :         }
   10242        15397 :         for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
   10243         7818 :             state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
   10244              :         }
   10245         7579 :         return;
   10246              :     }
   10247       582697 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
   10248       342688 :         state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = false;
   10249              :     }
   10250       582697 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
   10251       342688 :         state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = false;
   10252              :     }
   10253       240009 :     if (!state.dataGlobal->AndShadingControlInModel) {
   10254       235973 :         return;
   10255              :     }
   10256        16144 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
   10257       153368 :         for (int const SurfNum : state.dataViewFactor->EnclRadInfo(enclosureNum).SurfacePtr) {
   10258       141260 :             auto &surf = s_surf->Surface(SurfNum);
   10259       141260 :             auto &surfShade = s_surf->surfShades(SurfNum);
   10260       141260 :             bool surfShadingStatusChange = s_surf->SurfWinExtIntShadePrevTS(SurfNum) != s_surf->SurfWinShadingFlag(SurfNum) ||
   10261       141260 :                                            surf.activeShadedConstruction != surf.activeShadedConstructionPrev || surfShade.blind.movableSlats;
   10262       141260 :             if (surfShadingStatusChange) {
   10263            0 :                 state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
   10264            0 :                 state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
   10265            0 :                 break;
   10266              :             }
   10267              :         }
   10268              :     }
   10269              : }
   10270              : 
   10271            1 : DataSurfaces::WinShadingType findValueInEnumeration(Real64 controlValue)
   10272              : {
   10273              :     // This is a workaround to translate EMS Shading control numerical values
   10274              :     // EMS control of window shading devices involves setting the control values for shading control actuators with
   10275              :     // one of these values.  The variable names can be used or replaced, it is the whole number values that trigger
   10276              :     // changes in the modeling.
   10277              :     // Shades and Blinds are either fully on or fully off, partial positions require multiple windows.
   10278              :     // the window shading control flag values follow
   10279              :     // -1: if window has no shading device
   10280              :     // 0: if shading device is off
   10281              :     // 1: if interior shade is on
   10282              :     // 2: if glazing is switched to darker state
   10283              :     // 3: if exterior shade is on
   10284              :     // 4: if exterior screen is on
   10285              :     // 6: if interior blind is on
   10286              :     // 7: if exterior blind is on
   10287              :     // 8: if between-glass shade is on
   10288              :     // 9: if between-glass blind is on
   10289              :     // 10: window has interior shade that is off but may be triggered on later to control daylight glare
   10290              :     // 20: window has switchable glazing that is unswitched but may be switched later to control daylight glare or
   10291              :     // daylight illuminance 30: window has exterior shade that is off but may be triggered on later to control
   10292              :     // daylight glare or daylight illuminance 60: window has interior blind that is off but may be triggered on later
   10293              :     // to control daylight glare or daylight illuminance 70: window has exterior blind that is off but may be
   10294              :     // triggered on later to control daylight glare or daylight illuminance 80: window has between-glass shade that is
   10295              :     // off but may be triggered on later to control daylight glare or daylight illuminance 90: window has
   10296              :     // between-glass blind that is off but may be triggered on later to control daylight glare or daylight illuminance
   10297            1 :     if (controlValue == -1.0) {
   10298            0 :         return WinShadingType::NoShade;
   10299              :     }
   10300            1 :     if (controlValue == 0.0) {
   10301            0 :         return WinShadingType::ShadeOff;
   10302              :     }
   10303            1 :     if (controlValue == 1.0) {
   10304            1 :         return WinShadingType::IntShade;
   10305              :     }
   10306            0 :     if (controlValue == 2.0) {
   10307            0 :         return WinShadingType::SwitchableGlazing;
   10308              :     }
   10309            0 :     if (controlValue == 3.0) {
   10310            0 :         return WinShadingType::ExtShade;
   10311              :     }
   10312            0 :     if (controlValue == 4.0) {
   10313            0 :         return WinShadingType::ExtScreen;
   10314              :     }
   10315            0 :     if (controlValue == 6.0) {
   10316            0 :         return WinShadingType::IntBlind;
   10317              :     }
   10318            0 :     if (controlValue == 7.0) {
   10319            0 :         return WinShadingType::ExtBlind;
   10320              :     }
   10321            0 :     if (controlValue == 8.0) {
   10322            0 :         return WinShadingType::BGShade;
   10323              :     }
   10324            0 :     if (controlValue == 9.0) {
   10325            0 :         return WinShadingType::BGBlind;
   10326              :     }
   10327            0 :     if (controlValue == 10.0) {
   10328            0 :         return WinShadingType::IntShadeConditionallyOff;
   10329              :     }
   10330            0 :     if (controlValue == 20.0) {
   10331            0 :         return WinShadingType::GlassConditionallyLightened;
   10332              :     }
   10333            0 :     if (controlValue == 30.0) {
   10334            0 :         return WinShadingType::ExtShadeConditionallyOff;
   10335              :     }
   10336            0 :     if (controlValue == 60.0) {
   10337            0 :         return WinShadingType::IntBlindConditionallyOff;
   10338              :     }
   10339            0 :     if (controlValue == 70.0) {
   10340            0 :         return WinShadingType::ExtBlindConditionallyOff;
   10341              :     }
   10342            0 :     if (controlValue == 80.0) {
   10343            0 :         return WinShadingType::BGShadeConditionallyOff;
   10344              :     }
   10345            0 :     if (controlValue == 90.0) {
   10346            0 :         return WinShadingType::BGBlindConditionallyOff;
   10347              :     }
   10348            0 :     return WinShadingType::Invalid;
   10349              : }
   10350              : 
   10351        32364 : int selectActiveWindowShadingControlIndex(EnergyPlusData &state, int curSurface)
   10352              : {
   10353        32364 :     auto &s_surf = state.dataSurface;
   10354              :     // For a given surface, determine based on the schedules which index to the window shading control list vector
   10355              :     // should be active
   10356              :     // presume it is the first shading control - even if it is not active it needs to be some
   10357              :     // shading control which is then turned off in the WindowShadingManager
   10358        32364 :     if (s_surf->Surface(curSurface).windowShadingControlList.size() > 1) {
   10359            6 :         for (std::size_t listIndex = 0; listIndex < s_surf->Surface(curSurface).windowShadingControlList.size(); ++listIndex) {
   10360            6 :             int wsc = s_surf->Surface(curSurface).windowShadingControlList[listIndex];
   10361              :             // pick the first WindowShadingControl that has a non-zero schedule value
   10362            6 :             if (s_surf->WindowShadingControl(wsc).sched->getCurrentVal() > 0.0) {
   10363            3 :                 return listIndex;
   10364              :             }
   10365              :         }
   10366              :     }
   10367        32361 :     return 0;
   10368              : }
   10369              : 
   10370            0 : void WindowGapAirflowControl(EnergyPlusData &state)
   10371              : {
   10372              : 
   10373              :     // SUBROUTINE INFORMATION:
   10374              :     //       AUTHOR         Fred Winkelmann
   10375              :     //       DATE WRITTEN   February 2003
   10376              :     //       MODIFIED       June 2003, FCW: add fatal error for illegal schedule value
   10377              :     //       RE-ENGINEERED  na
   10378              : 
   10379              :     // PURPOSE OF THIS SUBROUTINE:
   10380              :     // For airflow windows, determines the airflow in the gap of
   10381              :     // double glazing and in the inner gap of triple glazing.
   10382              : 
   10383              :     // REFERENCES:
   10384              :     // na
   10385              : 
   10386            0 :     auto &s_surf = state.dataSurface;
   10387            0 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   10388            0 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   10389            0 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   10390            0 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   10391            0 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   10392            0 :             for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
   10393              : 
   10394            0 :                 s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
   10395            0 :                 if (s_surf->SurfWinMaxAirflow(ISurf) == 0.0) {
   10396            0 :                     continue;
   10397              :                 }
   10398            0 :                 if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) {
   10399            0 :                     continue;
   10400              :                 }
   10401            0 :                 switch (s_surf->SurfWinAirflowControlType(ISurf)) {
   10402            0 :                 case WindowAirFlowControlType::MaxFlow: {
   10403            0 :                     s_surf->SurfWinAirflowThisTS(ISurf) = s_surf->SurfWinMaxAirflow(ISurf);
   10404            0 :                 } break;
   10405            0 :                 case WindowAirFlowControlType::AlwaysOff: {
   10406            0 :                     s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
   10407            0 :                 } break;
   10408            0 :                 case WindowAirFlowControlType::Schedule: {
   10409            0 :                     if (s_surf->SurfWinAirflowHasSchedule(ISurf)) {
   10410            0 :                         auto const *sched = s_surf->SurfWinAirflowScheds(ISurf);
   10411            0 :                         Real64 ScheduleMult = sched->getCurrentVal(); // Multiplier value from schedule
   10412            0 :                         if (ScheduleMult < 0.0 || ScheduleMult > 1.0) {
   10413            0 :                             ShowFatalError(
   10414              :                                 state,
   10415            0 :                                 format("Airflow schedule has a value outside the range 0.0 to 1.0 for window={}", s_surf->Surface(ISurf).Name));
   10416              :                         }
   10417            0 :                         s_surf->SurfWinAirflowThisTS(ISurf) = ScheduleMult * s_surf->SurfWinMaxAirflow(ISurf);
   10418              :                     }
   10419            0 :                 } break;
   10420            0 :                 default:
   10421            0 :                     break;
   10422              :                 }
   10423              :             } // End of surface loop
   10424            0 :         } // End of space loop
   10425              :     } // End of zone loop
   10426            0 : }
   10427              : 
   10428          113 : void SkyDifSolarShading(EnergyPlusData &state)
   10429              : {
   10430              : 
   10431              :     // SUBROUTINE INFORMATION:
   10432              :     //       AUTHOR         Fred Winkelmann
   10433              :     //       DATE WRITTEN   May 1999
   10434              :     //       MODIFIED       Sep 2000, FCW: add IR view factor calc
   10435              :     //                      Sep 2002, FCW: correct error in expression for ground IR view factor.
   10436              :     //                         Affects only non-vertical surfaces that are shadowed. For these surfaces
   10437              :     //                         error caused underestimate of IR from ground and shadowing surfaces.
   10438              :     //                      Dec 2002; LKL: Sky Radiance Distribution now only anisotropic
   10439              :     //                      Nov 2003: FCW: modify to do sky solar shading of shadowing surfaces
   10440              :     //       RE-ENGINEERED  na
   10441              : 
   10442              :     // PURPOSE OF THIS SUBROUTINE:
   10443              :     // Calculates factors that account for shading of sky diffuse
   10444              :     // solar radiation by shadowing surfaces such as overhangs and detached
   10445              :     // shades.
   10446              :     // Called by PerformSolarCalculations
   10447              :     // For each exterior heat transfer surface calculates the following
   10448              :     // ratio (called DifShdgRatioIsoSky in this subroutine):
   10449              :     //  R1 = (Diffuse solar from sky dome on surface, with shading)/
   10450              :     //       (Diffuse solar from sky dome on surface, without shading)
   10451              :     // To calculate the incident diffuse radiation on a surface the sky
   10452              :     // hemisphere is divided into source elements ("patches"). Each patch
   10453              :     // is assumed to have the same radiance, i.e. the sky radiance is isotropic.
   10454              :     // The irradiance from each patch on a surface is calculated. Then these
   10455              :     // irradiances are summed to get the net irradiance on a surface, which
   10456              :     // the denominator of R1.
   10457              :     // To get the numerator of R1 the same summation is done, but for each surface
   10458              :     // and each patch the Shadow subroutine is called to determine how much
   10459              :     // radiation from a patch is blocked by shading surfaces.
   10460              :     // Also calculated is the following ratio (called DifShdgRatioHoriz in this routine):
   10461              :     //  R2 = (Diffuse solar from sky horizon band on surface, with shading)/
   10462              :     //       (Diffuse solar from sky horizon band on surface, without shading)
   10463              :     // For this ratio only a band of sky just above the horizon is considered.
   10464              :     // R1 and R2 are used in SUBROUTINE AnisoSkyViewFactors, which determines the
   10465              :     // sky diffuse solar irradiance on each exterior heat transfer surface each
   10466              :     // time step. In that routine the sky radiance distribution is a superposition
   10467              :     // of an isotropic distribution,
   10468              :     // a horizon brightening distribution and a circumsolar brightening distribution,
   10469              :     // where the proportion of each distribution depends
   10470              :     // on cloud cover, sun position and other factors. R1 multiplies the irradiance
   10471              :     // due to the isotropic component and R2 multiplies the irradiance due to the
   10472              :     // horizon brightening component.
   10473              :     // Calculates sky and ground IR view factors assuming sky IR is isotropic and
   10474              :     // shadowing surfaces are opaque to IR.
   10475              : 
   10476              :     // Using/Aliasing
   10477              : 
   10478              :     Real64 Fac1WoShdg;      // Intermediate calculation factor, without shading
   10479              :     Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
   10480              :     Real64 Fac1WithShdg;    // Intermediate calculation factor, with shading
   10481              :     Real64 SurfArea;        // Surface area (m2)
   10482              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgIsoSky     ! Diffuse solar irradiance from isotropic
   10483              :     //                                                          ! sky on surface, with shading
   10484              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgIsoSky       ! Diffuse solar from isotropic
   10485              :     //                                                           ! sky on surface, without shading
   10486              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgHoriz      ! Diffuse solar irradiance from horizon portion
   10487              :     // of
   10488              :     //                                                           ! sky on surface, with shading
   10489              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgHoriz        ! Diffuse solar irradiance from horizon portion
   10490              :     // of
   10491              :     //                                                           ! sky on surface, without shading
   10492              :     // INTEGER iHour,iTS
   10493              : 
   10494              :     // Initialize Surfaces Arrays
   10495          113 :     auto &s_surf = state.dataSurface;
   10496              : 
   10497          122 :     bool detailedShading = state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
   10498            9 :                            state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal;
   10499          113 :     state.dataSolarShading->SurfSunlitArea = 0.0;
   10500          113 :     state.dataSolarShading->SurfWithShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
   10501          113 :     state.dataSolarShading->SurfWoShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
   10502          113 :     state.dataSolarShading->SurfWithShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
   10503          113 :     state.dataSolarShading->SurfWoShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
   10504          113 :     state.dataSolarShading->SurfDifShdgRatioIsoSky.allocate(s_surf->TotSurfaces);
   10505          113 :     state.dataSolarShading->SurfDifShdgRatioHoriz.allocate(s_surf->TotSurfaces);
   10506              :     // initialized as no shading
   10507          113 :     state.dataSolarShading->SurfDifShdgRatioIsoSky = 1.0;
   10508          113 :     state.dataSolarShading->SurfDifShdgRatioHoriz = 1.0;
   10509          113 :     if (detailedShading) {
   10510            9 :         state.dataSolarShading->SurfCurDifShdgRatioIsoSky.dimension(s_surf->TotSurfaces, 1.0);
   10511            9 :         state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
   10512            9 :         state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS = 1.0;
   10513            9 :         state.dataSolarShading->SurfDifShdgRatioHorizHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
   10514            9 :         state.dataSolarShading->SurfDifShdgRatioHorizHRTS = 1.0;
   10515              :     }
   10516              : 
   10517          659 :     for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
   10518          546 :         auto &surf = s_surf->Surface(SurfNum);
   10519              : 
   10520              :         // CurrentModuleObject='Surfaces'
   10521          546 :         if (detailedShading) {
   10522          162 :             SetupOutputVariable(state,
   10523              :                                 "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
   10524              :                                 Constant::Units::None,
   10525           81 :                                 state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum),
   10526              :                                 OutputProcessor::TimeStepType::Zone,
   10527              :                                 OutputProcessor::StoreType::Average,
   10528           81 :                                 surf.Name);
   10529              :         } else {
   10530          930 :             SetupOutputVariable(state,
   10531              :                                 "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
   10532              :                                 Constant::Units::None,
   10533          465 :                                 state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum),
   10534              :                                 OutputProcessor::TimeStepType::Zone,
   10535              :                                 OutputProcessor::StoreType::Average,
   10536          465 :                                 surf.Name);
   10537              :         }
   10538         1092 :         SetupOutputVariable(state,
   10539              :                             "Debug Surface Solar Shading Model DifShdgRatioHoriz",
   10540              :                             Constant::Units::None,
   10541          546 :                             state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum),
   10542              :                             OutputProcessor::TimeStepType::Zone,
   10543              :                             OutputProcessor::StoreType::Average,
   10544          546 :                             surf.Name);
   10545         1092 :         SetupOutputVariable(state,
   10546              :                             "Debug Surface Solar Shading Model WithShdgIsoSky",
   10547              :                             Constant::Units::None,
   10548          546 :                             state.dataSolarShading->SurfWithShdgIsoSky(SurfNum),
   10549              :                             OutputProcessor::TimeStepType::Zone,
   10550              :                             OutputProcessor::StoreType::Average,
   10551          546 :                             surf.Name);
   10552         1092 :         SetupOutputVariable(state,
   10553              :                             "Debug Surface Solar Shading Model WoShdgIsoSky",
   10554              :                             Constant::Units::None,
   10555          546 :                             state.dataSolarShading->SurfWoShdgIsoSky(SurfNum),
   10556              :                             OutputProcessor::TimeStepType::Zone,
   10557              :                             OutputProcessor::StoreType::Average,
   10558          546 :                             surf.Name);
   10559          113 :     }
   10560              : 
   10561          791 :     for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
   10562          678 :         state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
   10563              : 
   10564        16950 :         for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
   10565        16272 :             state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
   10566        16272 :             state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
   10567              : 
   10568        94896 :             for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
   10569        78624 :                 auto &surf = s_surf->Surface(SurfNum);
   10570              : 
   10571              :                 // Cosine of angle of incidence on surface of solar radiation from patch
   10572       157248 :                 state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS.x * surf.OutNormVec.x +
   10573        78624 :                                                                    state.dataSolarShading->SUNCOS.y * surf.OutNormVec.y +
   10574        78624 :                                                                    state.dataSolarShading->SUNCOS.z * surf.OutNormVec.z;
   10575        16272 :             }
   10576              : 
   10577        16272 :             SHADOW(state, 24, 0);
   10578              : 
   10579        94896 :             for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
   10580        78624 :                 auto &surf = s_surf->Surface(SurfNum);
   10581              : 
   10582        78624 :                 if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) {
   10583        36252 :                     continue;
   10584              :                 }
   10585              : 
   10586        42372 :                 Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
   10587        42372 :                 SurfArea = surf.NetAreaShadowCalc;
   10588        42372 :                 if (SurfArea > Eps) {
   10589        42372 :                     FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
   10590              :                 } else {
   10591            0 :                     FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
   10592              :                 }
   10593        42372 :                 Fac1WithShdg = Fac1WoShdg * FracIlluminated;
   10594        42372 :                 state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
   10595        42372 :                 state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
   10596              : 
   10597              :                 // Horizon region
   10598        42372 :                 if (IPhi == 0) {
   10599         7047 :                     state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
   10600         7047 :                     state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
   10601              :                 }
   10602        16272 :             } // End of surface loop
   10603              :         } // End of Theta loop
   10604              :     } // End of Phi loop
   10605              : 
   10606          659 :     for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
   10607              : 
   10608          546 :         if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
   10609          494 :             state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
   10610          494 :                 (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
   10611              :         } else {
   10612           52 :             state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
   10613           52 :                 (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
   10614              :         }
   10615          546 :         if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
   10616          494 :             state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
   10617          494 :                 (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
   10618              :         } else {
   10619           52 :             state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
   10620           52 :                 (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
   10621              :         }
   10622          113 :     }
   10623              : 
   10624              :     // Get IR view factors. An exterior surface can receive IR radiation from
   10625              :     // sky, ground or shadowing surfaces. Assume shadowing surfaces have same
   10626              :     // temperature as outside air (and therefore same temperature as ground),
   10627              :     // so that the view factor to these shadowing surfaces can be included in
   10628              :     // the ground view factor. Sky IR is assumed to be isotropic and shadowing
   10629              :     // surfaces are assumed to be opaque to IR so they totally "shade" IR from
   10630              :     // sky or ground.
   10631              : 
   10632          943 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   10633          830 :         auto &surface = s_surf->Surface(SurfNum);
   10634          911 :         if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
   10635           81 :             state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
   10636          749 :             surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
   10637              :         } else {
   10638           81 :             surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(1, 1, SurfNum);
   10639              :         }
   10640          830 :         surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR;
   10641              : 
   10642          830 :         if (surface.SurfHasSurroundingSurfProperty) {
   10643            1 :             surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR - surface.ViewFactorSrdSurfs;
   10644              :         }
   10645              :     }
   10646              : 
   10647              :     //  DEALLOCATE(WithShdgIsoSky)
   10648              :     //  DEALLOCATE(WoShdgIsoSky)
   10649              :     //  DEALLOCATE(WithShdgHoriz)
   10650              :     //  DEALLOCATE(WoShdgHoriz)
   10651              : 
   10652          122 :     if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
   10653            9 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
   10654           90 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   10655          162 :             state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
   10656          162 :                 state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
   10657          162 :             state.dataSolarShading->SurfDifShdgRatioHorizHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
   10658          162 :                 state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
   10659              :         }
   10660              :     }
   10661          113 : }
   10662              : 
   10663        71216 : void CalcWindowProfileAngles(EnergyPlusData &state)
   10664              : {
   10665              : 
   10666              :     // SUBROUTINE INFORMATION:
   10667              :     //       AUTHOR         Fred Winkelmann
   10668              :     //       DATE WRITTEN   April 2002
   10669              :     //       MODIFIED       na
   10670              :     //       RE-ENGINEERED  na
   10671              :     // PURPOSE OF THIS SUBROUTINE:
   10672              :     // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
   10673              :     // Calculates horizontal and vertical beam solar profile angles
   10674              : 
   10675              :     Real64 ElevSun;       // Sun elevation; angle between sun and horizontal
   10676              :     Real64 ElevWin;       // Window elevation: angle between window outward normal and horizontal
   10677              :     Real64 AzimWin;       // Window azimuth (radians)
   10678              :     Real64 AzimSun;       // Sun azimuth (radians)
   10679              :     Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented window elements
   10680              :     // such as the top and bottom of a frame.
   10681              :     // This is the incidence angle in a plane that is normal to the window
   10682              :     // and parallel to the Y-axis of the window (the axis along
   10683              :     // which the height of the window is measured).
   10684              :     Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented elements
   10685              :     // such as the sides of a frame.
   10686              :     // This is the incidence angle in a plane that is normal to the window
   10687              :     // and parallel to the X-axis of the window (the axis along
   10688              :     // which the width of the window is measured).
   10689        71216 :     Vector3<Real64> WinNorm;                                  // Unit vector normal to window
   10690        71216 :     Vector3<Real64> WinNormCrossBase;                         // Cross product of WinNorm and vector along window baseline
   10691        71216 :     Vector3<Real64> SunPrime;                                 // Projection of sun vector onto plane (perpendicular to
   10692        71216 :     Vector3<Real64> const SolCosVec(state.dataEnvrn->SOLCOS); // Local Vector3 copy for speed (until SOLCOS mig to Vector3)
   10693              :     //  window plane) determined by WinNorm and vector along
   10694              :     //  baseline of window
   10695              :     Real64 ThWin; // Azimuth angle of WinNorm (radians)
   10696              :     Real64 dot1;
   10697              :     Real64 dot2;
   10698              :     Real64 dot3;
   10699              : 
   10700        71216 :     auto &s_surf = state.dataSurface;
   10701              : 
   10702        71216 :     ElevSun = Constant::PiOvr2 - std::acos(SolCosVec.z);
   10703        71216 :     AzimSun = std::atan2(SolCosVec.x, SolCosVec.y);
   10704              : 
   10705        71216 :     Real64 const cos_ElevSun = std::cos(ElevSun);
   10706        71216 :     Real64 const sin_ElevSun = std::sin(ElevSun);
   10707              : 
   10708       170521 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   10709       211316 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   10710       112011 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   10711       112011 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   10712       112011 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   10713       143115 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
   10714        31104 :                 auto &surf = s_surf->Surface(SurfNum);
   10715        31104 :                 if (surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt) {
   10716            0 :                     continue;
   10717              :                 }
   10718              : 
   10719        31104 :                 s_surf->SurfWinProfileAngHor(SurfNum) = 0.0;
   10720        31104 :                 s_surf->SurfWinProfileAngVert(SurfNum) = 0.0;
   10721        31104 :                 if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) {
   10722        14294 :                     continue;
   10723              :                 }
   10724              : 
   10725        16810 :                 ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
   10726        16810 :                 AzimWin = surf.Azimuth * Constant::DegToRad;
   10727              : 
   10728        16810 :                 ProfileAngHor = std::atan(sin_ElevSun / std::abs(cos_ElevSun * std::cos(AzimWin - AzimSun))) - ElevWin;
   10729              : 
   10730              :                 // CR9280 - were having negative profile angles on west sides.  commenting out previous code
   10731              :                 // (original code) for vertical windows
   10732              :                 //  IF(ABS(ElevWin) < 0.1d0) THEN  ! Near-vertical window
   10733              :                 //    ProfileAngVert = ABS(AzimWin-AzimSun)
   10734              :                 //  ELSE
   10735        16810 :                 WinNorm = surf.OutNormVec;
   10736        16810 :                 ThWin = AzimWin - Constant::PiOvr2;
   10737        16810 :                 Real64 const sin_Elevwin(std::sin(ElevWin));
   10738        16810 :                 WinNormCrossBase.x = -(sin_Elevwin * std::cos(ThWin));
   10739        16810 :                 WinNormCrossBase.y = sin_Elevwin * std::sin(ThWin);
   10740        16810 :                 WinNormCrossBase.z = std::cos(ElevWin);
   10741        16810 :                 SunPrime = SolCosVec - WinNormCrossBase * dot(SolCosVec, WinNormCrossBase);
   10742        16810 :                 dot1 = dot(WinNorm, SunPrime);
   10743        16810 :                 dot2 = SunPrime.magnitude();
   10744        16810 :                 dot3 = dot1 / dot2;
   10745        16810 :                 if (dot3 > 1.0) {
   10746            0 :                     dot3 = 1.0;
   10747        16810 :                 } else if (dot3 < -1.0) {
   10748            0 :                     dot3 = -1.0;
   10749              :                 }
   10750              :                 //    ProfileAngVert =
   10751              :                 //    ABS(ACOS(DOT_PRODUCT(WinNorm,SunPrime)/SQRT(DOT_PRODUCT(SunPrime,SunPrime))))
   10752        16810 :                 ProfileAngVert = std::abs(std::acos(dot3));
   10753              :                 //  END IF
   10754              :                 // Constrain to 0 to pi
   10755        16810 :                 if (ProfileAngVert > Constant::Pi) {
   10756            0 :                     ProfileAngVert = Constant::TwoPi - ProfileAngVert;
   10757              :                 }
   10758              : 
   10759        16810 :                 s_surf->SurfWinProfileAngHor(SurfNum) = ProfileAngHor / Constant::DegToRad;
   10760        16810 :                 s_surf->SurfWinProfileAngVert(SurfNum) = ProfileAngVert / Constant::DegToRad;
   10761        16810 :                 s_surf->SurfWinTanProfileAngHor(SurfNum) = std::abs(std::tan(ProfileAngHor));
   10762        16810 :                 s_surf->SurfWinTanProfileAngVert(SurfNum) = std::abs(std::tan(ProfileAngVert));
   10763              :             }
   10764        99305 :         }
   10765              :     }
   10766        71216 : }
   10767              : 
   10768           17 : void CalcFrameDividerShadow(EnergyPlusData &state,
   10769              :                             int const SurfNum,  // Surface number
   10770              :                             int const FrDivNum, // Frame/divider number
   10771              :                             int const HourNum   // Hour number
   10772              : )
   10773              : {
   10774              : 
   10775              :     // SUBROUTINE INFORMATION:
   10776              :     //       AUTHOR         Fred Winkelmann
   10777              :     //       DATE WRITTEN   June 2000
   10778              :     //       MODIFIED       Aug 2000, FW: add effective shadowing by inside
   10779              :     //                      projections
   10780              :     //       RE-ENGINEERED  na
   10781              : 
   10782              :     // PURPOSE OF THIS SUBROUTINE:
   10783              :     // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
   10784              :     // with a frame and/or divider. Using beam solar profile angles,
   10785              :     // calculates fraction of glass shaded by exterior frame and divider projections,
   10786              :     // The frame and divider profiles are assumed to be rectangular.
   10787              :     // A similar shadowing approach is used to calculate the fraction of glass area
   10788              :     // that produces beam solar illumination on interior frame and divider projections.
   10789              :     // This fraction is used in CalcWinFrameAndDividerTemps to determine the
   10790              :     // beam solar absorbed by inside projections. Beam solar reflected by inside projections
   10791              :     // is assumed to stay in the zone (as beam solar) although in actuality roughly
   10792              :     // half of this is reflected back onto the glass and the half that is reflected
   10793              :     // into the zone is diffuse.
   10794              :     // For multipane glazing the effect of solar absorbed by the exposed portion of
   10795              :     // frame or divider between the panes is not calculated. Beam solar incident on
   10796              :     // these portions is assumed to be transmitted into the zone unchanged.
   10797              :     // The shadowing of diffuse solar radiation by projections is not considered.
   10798              : 
   10799              :     Real64 ElevSun;       // Sun elevation; angle between sun and horizontal
   10800              :     Real64 ElevWin;       // Window elevation: angle between window outward normal and horizontal
   10801              :     Real64 AzimWin;       // Window azimuth (radians)
   10802              :     Real64 AzimSun;       // Sun azimuth (radians)
   10803              :     Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented projections
   10804              :     // such as the top and bottom of a frame or horizontal dividers.
   10805              :     // This is the incidence angle in a plane that is normal to the window
   10806              :     // and parallel to the Y-axis of the window (the axis along
   10807              :     // which the height of the window is measured).
   10808              :     Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented projections
   10809              :     // such as the top and bottom of a frame or horizontal dividers.
   10810              :     // This is the incidence angle in a plane that is normal to the window
   10811              :     // and parallel to the X-axis of the window (the axis along
   10812              :     // which the width of the window is measured).
   10813              :     Real64 TanProfileAngHor;  // Tangent of ProfileAngHor
   10814              :     Real64 TanProfileAngVert; // Tangent of ProfileAngVert
   10815              :     Real64 FrWidth;           // Frame width (m)
   10816              :     Real64 DivWidth;          // Divider width (m)
   10817              :     Real64 FrProjOut;         // Outside frame projection (m)
   10818              :     Real64 DivProjOut;        // Outside divider projection (m)
   10819              :     Real64 FrProjIn;          // Inside frame projection (m)
   10820              :     Real64 DivProjIn;         // Inside divider projection (m)
   10821              :     int NHorDiv;              // Number of horizontal dividers
   10822              :     int NVertDiv;             // Number of vertical dividers
   10823              :     Real64 GlArea;            // Glazed area (m2)
   10824              :     Real64 Arealite;          // Area of a single lite of glass (m2); glazed area, GlArea,
   10825              :     // if there is no divider (in which case there is only one lite).
   10826              :     Real64 ArealiteCol; // Area of a vertical column of lites (m2)
   10827              :     Real64 ArealiteRow; // Area of a horizontal row of lites (m2)
   10828              :     Real64 AshVDout;    // Shaded area from all vertical divider outside projections (m2)
   10829              :     Real64 AshVDin;     // Shaded area from all vertical divider inside projections (m2)
   10830              :     Real64 AshHDout;    // Shaded area from all horizontal divider outside projections (m2)
   10831              :     Real64 AshHDin;     // Shaded area from all horizontal divider inside projections (m2)
   10832              :     Real64 AshVFout;    // Shaded area from outside projection of vertical sides of frame (m2)
   10833              :     Real64 AshVFin;     // Shaded area from inside projection of vertical sides of frame (m2)
   10834              :     Real64 AshHFout;    // Shaded area from outside projection of horizontal sides
   10835              :     //   (top) of frame (m2)
   10836              :     Real64 AshHFin; // Shaded area from inside projection of horizontal sides
   10837              :     //   (top) of frame (m2)
   10838              :     Real64 AshDDover;   // Divider/divider shadow overlap area (m2)
   10839              :     Real64 AshFFover;   // Frame/frame shadow overlap area (m2)
   10840              :     Real64 AshFVDover;  // Frame/vertical divider overlap area (m2)
   10841              :     Real64 AshFHDover;  // Frame/horizontal divider overlap area (m2)
   10842              :     Real64 AshFDtotOut; // Total outside projection shadow area (m2)
   10843              :     Real64 AshFDtotIn;  // Total inside projection shadow area (m2)
   10844              :     Real64 FracShFDOut; // Fraction of glazing shadowed by frame and divider
   10845              :     //  outside projections
   10846              :     Real64 FracShFDin; // Fraction of glazing that illuminates frame and divider
   10847              :     //  inside projections with beam radiation
   10848              : 
   10849           17 :     Vector3<Real64> WinNorm(3);  // Window outward normal unit vector // Why the (3)?
   10850              :     Real64 ThWin;                // Azimuth angle of WinNorm
   10851           17 :     Vector3<Real64> SunPrime(3); // Projection of sun vector onto plane (perpendicular to // Why the (3)?
   10852              :     //  window plane) determined by WinNorm and vector along
   10853              :     //  baseline of window
   10854           17 :     Vector3<Real64> WinNormCrossBase(3); // Cross product of WinNorm and vector along window baseline // Why the (3)?
   10855              : 
   10856           17 :     auto &s_surf = state.dataSurface;
   10857              : 
   10858           17 :     if (s_surf->FrameDivider(FrDivNum).FrameProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).FrameProjectionIn == 0.0 &&
   10859           17 :         s_surf->FrameDivider(FrDivNum).DividerProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).DividerProjectionIn == 0.0) {
   10860            0 :         return;
   10861              :     }
   10862              : 
   10863           17 :     FrProjOut = s_surf->FrameDivider(FrDivNum).FrameProjectionOut;
   10864           17 :     FrProjIn = s_surf->FrameDivider(FrDivNum).FrameProjectionIn;
   10865           17 :     DivProjOut = s_surf->FrameDivider(FrDivNum).DividerProjectionOut;
   10866           17 :     DivProjIn = s_surf->FrameDivider(FrDivNum).DividerProjectionIn;
   10867              : 
   10868           17 :     auto &surf = s_surf->Surface(SurfNum);
   10869           17 :     GlArea = surf.Area;
   10870           17 :     ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
   10871           17 :     ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
   10872           17 :     AzimWin = surf.Azimuth * Constant::DegToRad;
   10873           17 :     AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
   10874              : 
   10875           17 :     ProfileAngHor = std::atan(std::sin(ElevSun) / std::abs(std::cos(ElevSun) * std::cos(AzimWin - AzimSun))) - ElevWin;
   10876           17 :     if (std::abs(ElevWin) < 0.1) { // Near-vertical window
   10877           17 :         ProfileAngVert = std::abs(AzimWin - AzimSun);
   10878              :     } else {
   10879            0 :         WinNorm = surf.OutNormVec;
   10880            0 :         ThWin = AzimWin - Constant::PiOvr2;
   10881            0 :         WinNormCrossBase(1) = -std::sin(ElevWin) * std::cos(ThWin);
   10882            0 :         WinNormCrossBase(2) = std::sin(ElevWin) * std::sin(ThWin);
   10883            0 :         WinNormCrossBase(3) = std::cos(ElevWin);
   10884            0 :         SunPrime = state.dataSolarShading->SUNCOS - WinNormCrossBase * dot(state.dataSolarShading->SUNCOS, WinNormCrossBase);
   10885            0 :         ProfileAngVert = std::abs(std::acos(dot(WinNorm, SunPrime) / magnitude(SunPrime)));
   10886              :     }
   10887              :     // Constrain to 0 to pi
   10888           17 :     if (ProfileAngVert > Constant::Pi) {
   10889            0 :         ProfileAngVert = 2 * Constant::Pi - ProfileAngVert;
   10890              :     }
   10891           17 :     TanProfileAngHor = std::abs(std::tan(ProfileAngHor));
   10892           17 :     TanProfileAngVert = std::abs(std::tan(ProfileAngVert));
   10893              : 
   10894           17 :     NHorDiv = s_surf->FrameDivider(FrDivNum).HorDividers;
   10895           17 :     NVertDiv = s_surf->FrameDivider(FrDivNum).VertDividers;
   10896           17 :     FrWidth = s_surf->FrameDivider(FrDivNum).FrameWidth;
   10897           17 :     DivWidth = s_surf->FrameDivider(FrDivNum).DividerWidth;
   10898              : 
   10899           17 :     Arealite = (surf.Height / (NHorDiv + 1.0) - DivWidth / 2.0) * (surf.Width / (NVertDiv + 1.0) - DivWidth / 2.0);
   10900           17 :     if (DivProjOut > 0.0 || DivProjIn > 0.0) {
   10901           17 :         ArealiteCol = (NHorDiv + 1) * Arealite;
   10902           17 :         ArealiteRow = (NVertDiv + 1) * Arealite;
   10903              :     } else {
   10904            0 :         ArealiteCol = GlArea;
   10905            0 :         ArealiteRow = GlArea;
   10906              :     }
   10907           17 :     AshVDout = 0.0;
   10908           17 :     AshVDin = 0.0;
   10909           17 :     AshHDout = 0.0;
   10910           17 :     AshHDin = 0.0;
   10911           17 :     AshVFout = 0.0;
   10912           17 :     AshVFin = 0.0;
   10913           17 :     AshHFout = 0.0;
   10914           17 :     AshHFin = 0.0;
   10915           17 :     AshDDover = 0.0;
   10916           17 :     AshFFover = 0.0;
   10917           17 :     AshFVDover = 0.0;
   10918           17 :     AshFHDover = 0.0;
   10919              : 
   10920           17 :     if (DivProjOut > 0.0 || DivProjIn > 0.0) {
   10921              : 
   10922              :         // Shaded area from all vertical dividers
   10923           17 :         AshVDout = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjOut * TanProfileAngVert, ArealiteCol);
   10924           17 :         AshVDin = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjIn * TanProfileAngVert, ArealiteCol);
   10925              : 
   10926              :         // Shaded area from all horizontal dividers
   10927           17 :         AshHDout = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjOut * TanProfileAngHor, ArealiteRow);
   10928           17 :         AshHDin = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjIn * TanProfileAngHor, ArealiteRow);
   10929              : 
   10930              :         // Horizontal divider/vertical divider shadow overlap
   10931           17 :         AshDDover = min(DivProjOut * TanProfileAngHor * DivProjOut * TanProfileAngVert, Arealite) * NHorDiv * NVertDiv;
   10932              :     }
   10933              : 
   10934           17 :     if (FrProjOut > 0.0 || FrProjIn > 0.0) {
   10935              : 
   10936              :         // Shaded area from sides of frame; to avoid complications from possible overlaps between
   10937              :         // shadow from side of frame and shadow from vertical divider the shaded area from side of
   10938              :         // frame is restricted to the area of one column of lites.
   10939           17 :         AshVFout = min((surf.Height - NHorDiv * DivWidth) * FrProjOut * TanProfileAngVert, ArealiteCol);
   10940           17 :         AshVFin = min((surf.Height - NHorDiv * DivWidth) * FrProjIn * TanProfileAngVert, ArealiteCol);
   10941              : 
   10942              :         // Shaded area from top or bottom of frame; to avoid complications from possible overlaps
   10943              :         // between shadow from top or bottom of frame and shadow from horizontal divider, the shaded
   10944              :         // area from the top or bottom of frame is restricted to the area of one row of lites.
   10945           17 :         AshHFout = min((surf.Width - NVertDiv * DivWidth) * FrProjOut * TanProfileAngHor, ArealiteRow);
   10946           17 :         AshHFin = min((surf.Width - NVertDiv * DivWidth) * FrProjIn * TanProfileAngHor, ArealiteRow);
   10947              : 
   10948              :         // Top/bottom of frame/side of frame shadow overlap
   10949           17 :         AshFFover = min(FrProjOut * TanProfileAngHor * FrProjOut * TanProfileAngVert, Arealite);
   10950           17 :         if (DivProjOut > 0.0) {
   10951              :             // Frame/vertical divider shadow overlap
   10952           17 :             AshFVDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NVertDiv;
   10953              :             // Frame/horizontal divider shadow overlap
   10954           17 :             AshFHDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NHorDiv;
   10955              :         }
   10956              :     }
   10957              : 
   10958           17 :     AshFDtotOut = AshVDout + AshHDout + AshVFout + AshHFout - (AshDDover + AshFFover + AshFVDover + AshFHDover);
   10959           17 :     AshFDtotIn =
   10960           17 :         (AshVDin + AshHDin) * s_surf->FrameDivider(FrDivNum).DividerSolAbsorp + (AshVFin + AshHFin) * s_surf->FrameDivider(FrDivNum).FrameSolAbsorp;
   10961              : 
   10962              :     // Divide by the glazed area of the window
   10963           17 :     FracShFDOut = AshFDtotOut / GlArea;
   10964           17 :     FracShFDin = AshFDtotIn / GlArea;
   10965           17 :     s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[HourNum] = 1.0 - FracShFDOut;
   10966           17 :     s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[HourNum] = 1.0 - (FracShFDin + FracShFDOut);
   10967           17 : }
   10968              : 
   10969            3 : void CalcBeamSolarOnWinRevealSurface(EnergyPlusData &state)
   10970              : {
   10971              : 
   10972              :     // SUBROUTINE INFORMATION:
   10973              :     //       AUTHOR         F. Winkelmann
   10974              :     //       DATE WRITTEN   April 2002
   10975              :     //       MODIFIED:na
   10976              :     //       RE-ENGINEERED:na
   10977              : 
   10978              :     // PURPOSE OF THIS SUBROUTINE
   10979              :     // Called by InitHeatGains when the sun is up.
   10980              :     // Calculates beam solar radiation absorbed and reflected by top, bottom,
   10981              :     // right and left sides of outside and inside window reveal surfaces.
   10982              :     // In doing this calculation, the shadowing on a reveal surface by other reveal surfaces
   10983              :     // is determined using the orientation of the reveal surfaces and the sun position.
   10984              :     // It is assumed that:
   10985              :     // (1) The window is an exterior window and is rectangular.
   10986              :     // (2) The reveal surfaces are perpendicular to the window plane.
   10987              :     // (3) If an exterior shade or blind is in place, there is no beam solar on
   10988              :     //     on exterior or interior reveal surfaces.
   10989              :     // (3) If an interior shade or blind is in place, there is no beam solar on
   10990              :     //     interior reveal surfaces.
   10991              :     // (4) The effect of window divider, if present, is ignored, including shadowing
   10992              :     //     of divider on inside reveal surfaces.
   10993              : 
   10994              :     // In the variable names, the "subscript" 1 = outside reveal, 2 = inside reveal
   10995              :     // The outside reveal surfaces (top, bottom, left, right) are assumed to have the same depth
   10996              :     // (given by Surface%Reveal and determined from vertices of window and vertices of parent
   10997              :     // wall) and the same solar absorptance. The inside reveal surfaces are divided into
   10998              :     // two categories: (1) the bottom reveal surface, called here the "inside sill;" and
   10999              :     // the other reveal surfaces (left, right and top). The left, right and top inside reveal
   11000              :     // surfaces are assumed to have the same depth and solar absorptance.
   11001              :     // The depth of the outside reveal is measured from the outside surface of the glazing;
   11002              :     // The depth of the inside sill and the other reveal surfaces is measured from the inside
   11003              :     // surface of the glazing. The inside sill is
   11004              :     // allowed to have depth and solar absorptance values that are different from the corresponding
   11005              :     // values for the other inside reveal surfaces. The inside sill depth is required to be
   11006              :     // greater than or equal to the depth of the other inside reveal surfaces. If the inside sill
   11007              :     // depth is greater than zero the depth of the other inside reveal surfaces is required to
   11008              :     // to be greater than zero.
   11009              :     // The reflection of beam solar radiation from all reveal surfaces is assumed to be isotropic
   11010              :     // diffuse; there is no specular component. Half of the beam solar reflected from outside
   11011              :     // reveal surfaces is assumed to go towards the window; the other half is assumed to go back
   11012              :     // to the exterior environment (i.e., reflection of this outward-going component from
   11013              :     // other outside reveal surfaces is not considered). The half that goes towards the window
   11014              :     // is added to the other radiation incident on the window.
   11015              :     // Correspondingly, half of the beam solar reflected from inside reveal surfaces is assumed
   11016              :     // to go towards the window, with the other half going into the zone (this half, and the portion
   11017              :     // going towards the window that is reflected) is added in CalcInteriorSolarDistribution
   11018              :     // to the variable BTOTzone, which is the total beam solar entering the zone as beam or diffuse.
   11019              :     // The portion going towards the window that is not reflected is absorbed in the glazing or
   11020              :     // transmitted back out into the exterior environment.
   11021              :     // The beam solar that is absorbed by outside reveal surfaces is added to the solar absorbed
   11022              :     // by the outside surface of the window's parent wall; similarly, the beam solar absorbed
   11023              :     // by the inside reveal surfaces is added to the solar absorbed by the inside surface of the
   11024              :     // parent wall (and is subtracted from BTOTzone).
   11025              :     // The net effect of beam solar reflected from outside reveal surfaces is to INCREASE the
   11026              :     // the heat gain to the zone, whereas the effect of beam solar reflected from interior reveal
   11027              :     // surfaces is to DECREASE the heat gain to the zone since part of this reflected solar is
   11028              :     // transmitted back out the window.
   11029              :     // If the window has a frame, the absorption of reflected beam solar by the inside and outside
   11030              :     // surfaces of the frame is considered. The shadowing of the frame onto interior reveal
   11031              :     // surfaces is also considered.
   11032              : 
   11033              :     // The total glazing thickness is taken to be the sum of the thickness of the glass layers
   11034              :     // and between-glass gas layers. If the window has an exterior, movable, storm window glass layer
   11035              :     // the presence of this layer and its adjacent air gap is considered in calculating the glazing
   11036              :     // properties (solar transmittance, etc.). But the storm window glass is assumed to be close
   11037              :     // enough to the rest of the glazing that its effect on total glazing thickness and outside
   11038              :     // reveal depth can be ignored.
   11039              : 
   11040              :     // METHODOLOGY EMPLOYED
   11041              :     // na
   11042              : 
   11043              :     // REFERENCES
   11044              :     // na
   11045              : 
   11046              :     // Locals
   11047              :     // SUBROUTINE ARGUMENT DEFINITIONS:na
   11048              : 
   11049              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS
   11050              : 
   11051              :     int ConstrNum;        // Construction number
   11052              :     int ConstrNumSh;      // Shaded construction number
   11053              :     Real64 CosBetaBottom; // Cosine of beam solar angle of incidence on bottom reveal
   11054              :     Real64 CosBetaLeft;   // Cosine of beam solar angle of incidence on left reveal
   11055              :     Real64 CosBeta;       // ABS of CosBetaBottom or CosBetaLeft
   11056              :     Real64 d1;            // Depth of outside reveal + half of glazing thickness (m)
   11057              :     Real64 d2;            // Depth of inside sill or of inside reveal plus half of glazing thickness (m)
   11058              :     Real64 d2prime;       // Depth of shadow cast on a reveal surface by opposite reveal (m)
   11059              :     Real64 d2prime2;      // Depth of shadow cast by frame onto inside reveal (m)
   11060              :     Real64 d12;           // d12 = d1 + d2 - d2prime (m)
   11061              :     Real64 TanAlpha;      // Tangent of horizontal or vertical profile angle
   11062              :     Real64 TanGamma;      // Tangent of vertical or horizontal profile angle
   11063              :     Real64 H;             // Window height, width (m)
   11064              :     Real64 W;
   11065              :     Real64 L;                    // Window height or width (m)
   11066              :     Real64 A1sh;                 // Shadowed area of outside horizontal or vertical reveal (m2)
   11067              :     Real64 A2sh;                 // Shadowed area of inside horizontal or vertical reveal (m2)
   11068              :     Real64 A1ill;                // Illuminated area of outside horizontal or vertical reveal (m2)
   11069              :     Real64 A2ill;                // Illuminated area of inside horizontal or vertical reveal (m2)
   11070              :     Real64 SolTransGlass;        // Beam solar transmittance of glazing
   11071              :     Real64 SolTransGlassSh;      // For switchable glazing, beam solar trans in switched state
   11072              :     Real64 DiffReflGlass;        // Diffuse back reflectance of glazing
   11073              :     Real64 DiffReflGlassSh;      // For switchable glazing, diffuse back refl in switched state
   11074              :     int HorVertReveal;           // Index: 1 = horizontal reveal, 2 = vertical reveal
   11075              :     Real64 OutsReveal;           // Depth of outside reveal (from outside glazing plane to outside wall plane) (m)
   11076              :     Real64 InsReveal;            // Depth of inside reveal (from inside glazing plane to inside wall plane (m)
   11077              :     Real64 InsSillDepth;         // Depth of inside sill, measured from innermost face of glazing (m)
   11078              :     Real64 GlazingThickness;     // Thickness of glazing, measured from innermost face to outermost face (m)
   11079              :     Real64 InsideRevealSolAbs;   // Solar absorptance of inside reveal or inside sill
   11080              :     Real64 BmSolRefldOutsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
   11081              :     //  outside reveal surface (m2)
   11082              :     Real64 BmSolRefldInsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
   11083              :     //  inside reveal surface (m2)
   11084              :     WinShadingType ShadeFlag; // Shading flag
   11085              :     int FrameDivNum;          // Frame/Divider number
   11086              :     Real64 FrameWidth;        // Frame width (m)
   11087              :     Real64 P1;                // Frame outside/inside projection plus half of glazing thickness (m)
   11088              :     Real64 P2;
   11089              :     Real64 f1; // f1=d1-P1, f2=d2-P2 (m)
   11090              :     Real64 f2;
   11091              :     Real64 L1; // Average distance of outside/inside illuminated area to frame;
   11092              :     Real64 L2;
   11093              :     // used in calculating view factor to frame (m)
   11094              :     Real64 FracToGlassOuts;   // View factor from outside horizontal or vertical reveal to glass
   11095              :     Real64 FracToGlassIns;    // View factor from inside horizontal or vertical reveal to glass
   11096              :     Real64 TanProfileAngVert; // Tangent of vertical profile angle (the profile angle appropriate for
   11097              :     // vertical reveal surfaces.
   11098              :     Real64 TanProfileAngHor; // Tangent of horizontal profile angle (the profile angle appropriate for
   11099              :     // horizontal reveal surfaces.
   11100              : 
   11101              :     Real64 tmp_SunlitFracWithoutReveal; // Temporary variable
   11102              : 
   11103            3 :     auto &s_surf = state.dataSurface;
   11104              : 
   11105            6 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   11106            6 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   11107            3 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   11108            3 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   11109            3 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   11110            9 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
   11111              :                 // Added TH for initialization. CR 7596 inside reveal causing high cooling loads
   11112              :                 // for outside reveals
   11113            6 :                 s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
   11114            6 :                 s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
   11115            6 :                 s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) = 0.0;
   11116            6 :                 s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
   11117            6 :                 s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
   11118              :                 // for inside reveals
   11119            6 :                 s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
   11120            6 :                 s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
   11121            6 :                 s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
   11122            6 :                 s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
   11123            6 :                 s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) = 0.0;
   11124            6 :                 s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
   11125            6 :                 s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
   11126            6 :                 s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
   11127            6 :                 s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
   11128            6 :                 s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
   11129            6 :                 s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
   11130              : 
   11131            6 :                 auto &surf = s_surf->Surface(SurfNum);
   11132            6 :                 if ((surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt)) {
   11133            0 :                     continue;
   11134              :                 }
   11135            6 :                 if (surf.Reveal == 0.0 && s_surf->SurfWinInsideReveal(SurfNum) == 0.0 && s_surf->SurfWinInsideSillDepth(SurfNum) == 0.0) {
   11136            0 :                     continue;
   11137              :                 }
   11138            6 :                 if (surf.Sides != 4) {
   11139            0 :                     continue;
   11140              :                 }
   11141            6 :                 if (s_surf->SurfWinInsideSillDepth(SurfNum) < s_surf->SurfWinInsideReveal(SurfNum)) {
   11142            0 :                     continue;
   11143              :                 }
   11144              : 
   11145            6 :                 ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
   11146            6 :                 if ((ShadeFlag == WinShadingType::ExtShade) || (ShadeFlag == WinShadingType::ExtBlind)) {
   11147            0 :                     continue;
   11148              :                 }
   11149              : 
   11150            6 :                 if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) {
   11151            0 :                     continue;
   11152              :                 }
   11153              : 
   11154            6 :                 tmp_SunlitFracWithoutReveal =
   11155            6 :                     state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
   11156              : 
   11157              :                 // Calculate cosine of angle of incidence of beam solar on reveal surfaces,
   11158              :                 // assumed to be perpendicular to window plane
   11159              : 
   11160            6 :                 CosBetaBottom = -state.dataEnvrn->SOLCOS(1) * surf.SinAzim * surf.CosTilt - state.dataEnvrn->SOLCOS(2) * surf.CosAzim * surf.CosTilt +
   11161            6 :                                 state.dataEnvrn->SOLCOS(3) * surf.SinTilt;
   11162              : 
   11163            6 :                 CosBetaLeft = -state.dataEnvrn->SOLCOS(1) * surf.CosAzim - state.dataEnvrn->SOLCOS(2) * surf.SinAzim;
   11164              : 
   11165              :                 // Note: CosBetaTop = -CosBetaBottom, CosBetaRight = -CosBetaLeft
   11166              : 
   11167            6 :                 OutsReveal = surf.Reveal;
   11168            6 :                 InsReveal = s_surf->SurfWinInsideReveal(SurfNum);
   11169            6 :                 InsideRevealSolAbs = 0.0;
   11170            6 :                 GlazingThickness = s_surf->SurfWinTotGlazingThickness(SurfNum);
   11171            6 :                 H = surf.Height;
   11172            6 :                 W = surf.Width;
   11173            6 :                 d1 = OutsReveal + 0.5 * GlazingThickness;
   11174            6 :                 ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
   11175            6 :                 ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
   11176            6 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
   11177              : 
   11178            6 :                 SolTransGlass = Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
   11179            6 :                                               thisConstruct.TransSolBeamCoef);
   11180            6 :                 TanProfileAngVert = s_surf->SurfWinTanProfileAngVert(SurfNum);
   11181            6 :                 TanProfileAngHor = s_surf->SurfWinTanProfileAngHor(SurfNum);
   11182            6 :                 FrameDivNum = surf.FrameDivider;
   11183            6 :                 FrameWidth = 0.0;
   11184            6 :                 if (FrameDivNum != 0) {
   11185            6 :                     FrameWidth = s_surf->FrameDivider(FrameDivNum).FrameWidth;
   11186            6 :                     if (FrameWidth > 0.0) {
   11187            6 :                         P1 = s_surf->FrameDivider(FrameDivNum).FrameProjectionOut + 0.5 * GlazingThickness;
   11188            6 :                         P2 = s_surf->FrameDivider(FrameDivNum).FrameProjectionIn + 0.5 * GlazingThickness;
   11189            6 :                         if (OutsReveal + 0.5 * GlazingThickness <= P1) {
   11190            6 :                             d1 = P1 + 0.001;
   11191              :                         }
   11192              :                     }
   11193              :                 }
   11194              :                 // Loop over vertical and horizontal reveal surfaces
   11195           18 :                 for (HorVertReveal = 1; HorVertReveal <= 2; ++HorVertReveal) {
   11196              : 
   11197           12 :                     FracToGlassOuts = 0.5;
   11198           12 :                     FracToGlassIns = 0.5;
   11199           12 :                     BmSolRefldOutsReveal = 0.0;
   11200           12 :                     BmSolRefldInsReveal = 0.0;
   11201           12 :                     A1ill = 0.0;
   11202           12 :                     A2ill = 0.0;
   11203              : 
   11204              :                     // Added TH. 5/27/2009
   11205           12 :                     A1sh = 0.0;
   11206           12 :                     A2sh = 0.0;
   11207              : 
   11208           12 :                     if (HorVertReveal == 1) { // Vertical reveal
   11209            6 :                         TanAlpha = TanProfileAngHor;
   11210            6 :                         TanGamma = TanProfileAngVert;
   11211            6 :                         CosBeta = std::abs(CosBetaLeft);
   11212            6 :                         L = surf.Height;
   11213            6 :                         d2 = InsReveal + 0.5 * GlazingThickness;
   11214            6 :                         d2prime = d1 + d2 - W / TanGamma;
   11215            6 :                         InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
   11216              :                     } else { // Horizontal reveal
   11217            6 :                         InsSillDepth = s_surf->SurfWinInsideSillDepth(SurfNum);
   11218            6 :                         TanAlpha = TanProfileAngVert;
   11219            6 :                         TanGamma = TanProfileAngHor;
   11220            6 :                         CosBeta = std::abs(CosBetaBottom);
   11221            6 :                         L = surf.Width;
   11222            6 :                         if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
   11223            6 :                             d2 = InsSillDepth + 0.5 * GlazingThickness;
   11224            6 :                             InsideRevealSolAbs = s_surf->SurfWinInsideSillSolAbs(SurfNum);
   11225              :                         } else { // Top reveal surfaces may be illuminated
   11226            0 :                             d2 = InsReveal + 0.5 * GlazingThickness;
   11227            0 :                             InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
   11228              :                         }
   11229            6 :                         d2prime = d1 + d2 - H / TanGamma;
   11230              :                     }
   11231           12 :                     if (d2prime < 0.0) {
   11232            0 :                         d2prime = 0.0; // No shadow from opposing reveal
   11233              :                     }
   11234           12 :                     d12 = d1 + d2 - d2prime;
   11235              : 
   11236           12 :                     if (FrameWidth <= 0.001) {
   11237              :                         // Window without frame
   11238              : 
   11239              :                         // Find inside and outside shadowed area of vertical or horizontal reveal surfaces
   11240              :                         // that can be illuminated by beam solar; shadowing is by other reveal surfaces.
   11241              : 
   11242            0 :                         if (d2prime <= d2) {
   11243            0 :                             if (d12 * TanAlpha <= L) {
   11244            0 :                                 A1sh = 0.5 * TanAlpha * pow_2(d1);
   11245            0 :                                 A2sh = d2prime * L + 0.5 * TanAlpha * pow_2(d12) - A1sh;
   11246              :                             } else { // d12*TanAlpha > L
   11247            0 :                                 if (d1 * TanAlpha <= L) {
   11248            0 :                                     A1sh = 0.5 * TanAlpha * pow_2(d1);
   11249            0 :                                     A2sh = d2 * L - 0.5 * TanAlpha * pow_2(L / TanAlpha - d1);
   11250              :                                 } else { // d1*TanAlpha > L
   11251            0 :                                     A1sh = d1 * L - (0.5 / TanAlpha) * pow_2(L);
   11252            0 :                                     A2sh = d2 * L;
   11253              :                                 }
   11254              :                             }
   11255              :                         } else { // d2prime > d2
   11256            0 :                             A2sh = d2 * L;
   11257            0 :                             if (d2prime < d1 + d2) {
   11258            0 :                                 if (d12 * TanAlpha <= L) {
   11259            0 :                                     A1sh = L * (d2prime - d2) + 0.5 * TanAlpha * pow_2(d12);
   11260              :                                 } else { // d12*TanAlpha > L
   11261            0 :                                     A1sh = d1 * L - 0.5 * pow_2(L) / TanAlpha;
   11262              :                                 }
   11263              :                             } else { // d2prime >= d1+d2
   11264            0 :                                 A1sh = d1 * L;
   11265              :                             }
   11266              :                         }
   11267              : 
   11268              :                         // Added TH. 5/27/2009
   11269            0 :                         if (A1sh < 0.0) {
   11270            0 :                             A1sh = 0.0;
   11271              :                         }
   11272            0 :                         if (A2sh < 0.0) {
   11273            0 :                             A2sh = 0.0;
   11274              :                         }
   11275              : 
   11276            0 :                         if (OutsReveal >= 0.001) {
   11277            0 :                             A1ill = d1 * L - A1sh; // A1ill = 0.0 if OutsReveal < 0.001
   11278              :                         }
   11279            0 :                         if (InsReveal >= 0.001) {
   11280            0 :                             A2ill = d2 * L - A2sh; // A2ill = 0.0 if InsReveal < 0.001
   11281              :                         }
   11282              : 
   11283              :                     } else { // Window with frame; take into account shadowing
   11284              :                         // of inside reveal surfaces by frame
   11285           12 :                         f1 = d1 - P1;
   11286           12 :                         f2 = d2 - P2;
   11287           12 :                         d2prime2 = FrameWidth / TanGamma;
   11288           12 :                         if (HorVertReveal == 1) { // Vertical reveal
   11289            6 :                             if (InsReveal + 0.5 * GlazingThickness <= P2) {
   11290            0 :                                 d2 = P2 + 0.001;
   11291              :                             }
   11292              :                         } else {                       // Horizontal
   11293            6 :                             if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
   11294            6 :                                 if (InsSillDepth + 0.5 * GlazingThickness <= P2) {
   11295            0 :                                     d2 = P2 + 0.001;
   11296              :                                 }
   11297              :                             } else { // Top reveal surfaces may be illuminated
   11298            0 :                                 if (InsReveal + 0.5 * GlazingThickness <= P2) {
   11299            0 :                                     d2 = P2 + 0.001;
   11300              :                                 }
   11301              :                             }
   11302              :                         }
   11303              : 
   11304           12 :                         if (d2prime <= f2) { // Shadow from opposing reveal does not go beyond inside surface of frame
   11305              : 
   11306           10 :                             if (d12 * TanAlpha <= L) {
   11307            5 :                                 A1sh = 0.5 * TanAlpha * pow_2(f1);
   11308            5 :                                 L1 = f1 * (f1 * TanAlpha / (6.0 * L) + 0.5);
   11309            5 :                                 if (d2 - (d2prime + d2prime2 + P2) >= 0.0) {
   11310            5 :                                     A2sh = (d2prime + d2prime2) * L + 0.5 * TanAlpha * (pow_2(d1 + d2 - d2prime) - pow_2(d1 + P2 + d2prime2));
   11311            5 :                                     L2 = d2prime2 + 0.5 * (d2 - (d2prime + d2prime2 + P2));
   11312              :                                 } else { // d2-(d2prime+d2prime2+P2) < 0.  ! Inside reveal is fully shadowed by
   11313              :                                          // frame and/or opposing reveal
   11314            0 :                                     A2sh = f2 * L;
   11315            0 :                                     L2 = f2;
   11316              :                                 }
   11317              :                             } else { // d12*TanAlpha >= L
   11318            5 :                                 if ((d1 + P2) * TanAlpha <= L) {
   11319            5 :                                     A1sh = 0.5 * TanAlpha * pow_2(f1);
   11320            5 :                                     L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
   11321            5 :                                     if ((d1 + P2 + d2prime2) * TanAlpha >= L) {
   11322            0 :                                         A2sh = f2 * L;
   11323            0 :                                         L2 = f2;
   11324              :                                     } else { // (d1+P2+d2prime2)*TanAlpha < L
   11325            5 :                                         A2sh = f2 * L - 0.5 * pow_2(L - (d1 + P2) * TanAlpha) / TanAlpha +
   11326            5 :                                                d2prime2 * (L - (d1 + P2 + d2prime2 / 2.0) * TanAlpha);
   11327            5 :                                         L2 = d2prime2 + (L / TanAlpha - (d1 + P2 + d2prime2)) / 3.0;
   11328              :                                     }
   11329              :                                 } else { // (d1+P2)*TanAlpha > L
   11330            0 :                                     L2 = f2;
   11331            0 :                                     A2sh = f2 * L;
   11332            0 :                                     if (f1 * TanAlpha <= L) {
   11333            0 :                                         A1sh = 0.5 * TanAlpha * pow_2(f1);
   11334            0 :                                         L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
   11335              :                                     } else { // f1*TanAlpha > L
   11336            0 :                                         A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
   11337            0 :                                         L1 = f1 - (L / TanAlpha) / 3.0;
   11338              :                                     }
   11339              :                                 }
   11340              :                             }
   11341              : 
   11342              :                         } else { // d2prime > f2   ! Shadow from opposing reveal goes beyond inside of frame
   11343              : 
   11344            2 :                             A2sh = f2 * L;
   11345            2 :                             L2 = f2;
   11346            2 :                             if (d2prime >= d1 + d2) {
   11347            0 :                                 A1sh = 0.0;
   11348            0 :                                 L1 = f1;
   11349              :                             } else { // d2prime < d1+d2
   11350            2 :                                 if (d2prime <= d2 + P1) {
   11351            2 :                                     if (f1 * TanAlpha <= L) {
   11352            2 :                                         A1sh = 0.5 * TanAlpha * pow_2(f1);
   11353            2 :                                         L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
   11354              :                                     } else { // f1*TanAlpha > L
   11355            0 :                                         A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
   11356            0 :                                         L1 = f1 - (L / TanAlpha) / 3.0;
   11357              :                                     }
   11358              :                                 } else { // d2prime > d2+P1
   11359            0 :                                     if (d12 * TanAlpha <= L) {
   11360            0 :                                         A1sh = L * (d2prime - (d2 + P1)) + 0.5 * TanAlpha * pow_2(d12);
   11361            0 :                                         L1 = (L * (f1 - d12 / 2.0) - d12 * TanAlpha * (f1 / 2 - d12 / 3.0)) / (L - d12 * TanAlpha / 2.0);
   11362              :                                     } else { // d12*TanAlpha > L
   11363            0 :                                         A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
   11364            0 :                                         L1 = f1 - (L / TanAlpha) / 3.0;
   11365              :                                     }
   11366              :                                 }
   11367              :                             }
   11368              :                         }
   11369              : 
   11370              :                         // Added TH. 5/27/2009
   11371           12 :                         if (A1sh < 0.0) {
   11372            0 :                             A1sh = 0.0;
   11373              :                         }
   11374           12 :                         if (A2sh < 0.0) {
   11375            0 :                             A2sh = 0.0;
   11376              :                         }
   11377              : 
   11378           12 :                         if (OutsReveal >= P1 + 0.5 * GlazingThickness + 0.001) {
   11379            0 :                             A1ill = L * f1 - A1sh;
   11380              :                         }
   11381           12 :                         if (InsReveal >= P2 + 0.5 * GlazingThickness + 0.001) {
   11382           12 :                             A2ill = L * f2 - A2sh;
   11383              :                         }
   11384           12 :                         if (L1 == 0.0) {
   11385            0 :                             FracToGlassOuts = 0.0;
   11386              :                         } else {
   11387           12 :                             FracToGlassOuts = 0.5 * (1.0 - std::atan(FrameWidth / L1) / Constant::PiOvr2);
   11388              :                         }
   11389           12 :                         if (L2 == 0.0) {
   11390            0 :                             FracToGlassIns = 0.0;
   11391              :                         } else {
   11392           12 :                             FracToGlassIns = 0.5 * (1.0 - std::atan(FrameWidth / L2) / Constant::PiOvr2);
   11393              :                         }
   11394              :                     } // End of check if window has frame
   11395              : 
   11396              :                     // Added TH. 5/27/2009
   11397           12 :                     if (A1ill < 0.0) {
   11398            0 :                         A1ill = 0.0;
   11399              :                     }
   11400           12 :                     if (A2ill < 0.0) {
   11401            0 :                         A2ill = 0.0;
   11402              :                     }
   11403              : 
   11404              :                     // Quantities related to outside reveal
   11405           12 :                     if (A1ill > Constant::OneMillionth) {
   11406              : 
   11407            0 :                         s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) +=
   11408            0 :                             A1ill * s_surf->SurfWinOutsideRevealSolAbs(SurfNum) * CosBeta * tmp_SunlitFracWithoutReveal;
   11409              : 
   11410            0 :                         BmSolRefldOutsReveal = A1ill * (1.0 - s_surf->SurfWinOutsideRevealSolAbs(SurfNum)) * CosBeta * tmp_SunlitFracWithoutReveal;
   11411              : 
   11412            0 :                         s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) += state.dataEnvrn->BeamSolarRad * BmSolRefldOutsReveal;
   11413            0 :                         s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) =
   11414            0 :                             s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
   11415              : 
   11416              :                         // Reflected solar from outside horizontal and vertical reveal incident on glazing
   11417            0 :                         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) += FracToGlassOuts * BmSolRefldOutsReveal / surf.Area;
   11418              : 
   11419            0 :                         if (FrameWidth > 0.0) {
   11420              :                             // Reflected solar from outside horizontal and vertical reveal incident on frame
   11421            0 :                             s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) +=
   11422            0 :                                 (0.5 - FracToGlassOuts) * BmSolRefldOutsReveal / s_surf->SurfWinFrameArea(SurfNum);
   11423              :                         }
   11424              : 
   11425              :                     } // End of check if A1ill > 0.0 (actually 10^-6)
   11426              : 
   11427              :                     // Quantities related to inside reveal; inside reveal reflection/absorption is assumed
   11428              :                     // to occur only if an interior shade or blind is not in place.
   11429              : 
   11430           12 :                     if (NOT_SHADED(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
   11431              : 
   11432           12 :                         if (A2ill > Constant::OneMillionth) {
   11433              : 
   11434           10 :                             DiffReflGlass = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11435           10 :                             if (ShadeFlag == WinShadingType::SwitchableGlazing) {
   11436            0 :                                 auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
   11437              :                                 SolTransGlassSh =
   11438            0 :                                     Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
   11439            0 :                                                   thisConstructSh.TransSolBeamCoef);
   11440            0 :                                 SolTransGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), SolTransGlass, SolTransGlassSh);
   11441            0 :                                 DiffReflGlassSh = thisConstructSh.ReflectSolDiffBack;
   11442            0 :                                 DiffReflGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), DiffReflGlass, DiffReflGlassSh);
   11443              :                             }
   11444              : 
   11445              :                             // Calc beam solar absorbed (m2)
   11446           10 :                             s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +=
   11447           10 :                                 A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
   11448              : 
   11449              :                             // Added TH 5/26/2009 for reporting purpose - Beam solar absorbed by the inside reveal
   11450              :                             // (W)
   11451           10 :                             s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) +=
   11452           10 :                                 state.dataEnvrn->BeamSolarRad * A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
   11453              : 
   11454              :                             // in m2 = Area * solar transmitted fraction * inside reveal reflection fraction
   11455           10 :                             BmSolRefldInsReveal = A2ill * SolTransGlass * (1.0 - InsideRevealSolAbs) * CosBeta * tmp_SunlitFracWithoutReveal;
   11456              : 
   11457           10 :                             s_surf->SurfWinBmSolRefldInsReveal(SurfNum) += BmSolRefldInsReveal;
   11458              : 
   11459           10 :                             s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) +=
   11460           10 :                                 state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal; // W, BeamSolarRad in W/m2
   11461           10 :                             s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) =
   11462           10 :                                 s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
   11463              : 
   11464              :                             // Reflected solar from inside horizontal and vertical reveal incident on glazing
   11465           10 :                             s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) += FracToGlassIns * BmSolRefldInsReveal / surf.Area;
   11466              : 
   11467              :                             // Added TH 5/26/2009 for reporting purpose - diffuse on window glass from inside
   11468              :                             // reveal (W)
   11469           10 :                             s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) +=
   11470           10 :                                 state.dataEnvrn->BeamSolarRad * FracToGlassIns * BmSolRefldInsReveal;
   11471              : 
   11472              :                             // Reflected solar from inside horizontal and vertical reveal incident on frame
   11473           10 :                             if (FrameWidth > 0.0) {
   11474           10 :                                 s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) +=
   11475           10 :                                     (0.5 - FracToGlassIns) * BmSolRefldInsReveal / s_surf->SurfWinFrameArea(SurfNum);
   11476              : 
   11477              :                                 // Added TH 5/26/2009 for reporting purpose - diffuse on window frame from inside
   11478              :                                 // reveal (W)
   11479           10 :                                 s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) +=
   11480           10 :                                     state.dataEnvrn->BeamSolarRad * (0.5 - FracToGlassIns) * BmSolRefldInsReveal;
   11481              :                             }
   11482              : 
   11483              :                             // Reflected solar from inside reveal going directly into zone and reflected from
   11484              :                             // glass. Assumes half of solar reflected from inside reveal goes as diffuse radiation
   11485              :                             // into the zone and half goes as diffuse radiation towards window.
   11486           10 :                             s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) += BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
   11487              : 
   11488              :                             // Added TH 5/26/2009 for reporting purpose - diffuse into zone from inside reveal (W)
   11489           10 :                             s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) +=
   11490           10 :                                 state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
   11491              : 
   11492              :                         } // End of check if A2ill > 0.0 (actually 10^-6)
   11493              : 
   11494              :                     } // End of check if interior shade or blind is in place
   11495              : 
   11496              :                 } // End of loop over vertical and horizontal reveal
   11497              : 
   11498              :             } // End of surface loop
   11499            3 :         }
   11500              :     }
   11501            3 : }
   11502              : 
   11503       249964 : void ReportSurfaceShading(EnergyPlusData &state)
   11504              : {
   11505              : 
   11506              :     // SUBROUTINE INFORMATION:
   11507              :     //       AUTHOR         Linda Lawrie
   11508              :     //       DATE WRITTEN   April 2000
   11509              :     //       MODIFIED       na
   11510              :     //       RE-ENGINEERED  na
   11511              : 
   11512              :     // PURPOSE OF THIS SUBROUTINE:
   11513              :     // This subroutine uses the internal variables used in the Shading
   11514              :     // calculations and prepares them for reporting (at timestep level).
   11515              : 
   11516              :     // METHODOLOGY EMPLOYED:
   11517              :     // Because all of the calculations are done on a "daily" basis in this
   11518              :     // module, it is difficult to formulate the values that might be useful
   11519              :     // for reporting.  SunlitFrac was the first of these two arrays to be
   11520              :     // made into "two dimensions".  It is not clear that both have to be
   11521              :     // two dimensions.
   11522              : 
   11523              :     // REFERENCES:
   11524              :     // na
   11525              : 
   11526              :     // Using/Aliasing
   11527              :     using namespace OutputReportPredefined;
   11528              : 
   11529              :     // Locals
   11530              :     // SUBROUTINE ARGUMENT DEFINITIONS:
   11531              :     // na
   11532              : 
   11533              :     // SUBROUTINE PARAMETER DEFINITIONS:
   11534              :     // na
   11535              : 
   11536              :     // INTERFACE BLOCK SPECIFICATIONS
   11537              :     // na
   11538              : 
   11539              :     // DERIVED TYPE DEFINITIONS
   11540              :     // na
   11541              : 
   11542              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11543              :     int SurfNum; // Loop Counter
   11544              :     int RepCol;  // the column of the predefined report
   11545              : 
   11546       249964 :     auto &s_surf = state.dataSurface;
   11547      2353997 :     for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   11548      2104033 :         auto &surf = s_surf->Surface(SurfNum);
   11549              : 
   11550      2104033 :         s_surf->SurfSunlitFrac(SurfNum) = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
   11551      2104033 :         s_surf->SurfSunlitArea(SurfNum) =
   11552      2104033 :             state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) * surf.Area;
   11553              :     }
   11554              :     // added for predefined reporting
   11555       249964 :     RepCol = 0;
   11556       249964 :     if (state.dataEnvrn->Month == 3 && state.dataEnvrn->DayOfMonth == 21) {
   11557            0 :         if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
   11558            0 :             RepCol = state.dataOutRptPredefined->pdchSlfMar21_9;
   11559            0 :         } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
   11560            0 :             RepCol = state.dataOutRptPredefined->pdchSlfMar21_12;
   11561            0 :         } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
   11562            0 :             RepCol = state.dataOutRptPredefined->pdchSlfMar21_15;
   11563              :         }
   11564       249964 :     } else if (state.dataEnvrn->Month == 6 && state.dataEnvrn->DayOfMonth == 21) {
   11565            0 :         if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
   11566            0 :             RepCol = state.dataOutRptPredefined->pdchSlfJun21_9;
   11567            0 :         } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
   11568            0 :             RepCol = state.dataOutRptPredefined->pdchSlfJun21_12;
   11569            0 :         } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
   11570            0 :             RepCol = state.dataOutRptPredefined->pdchSlfJun21_15;
   11571              :         }
   11572       249964 :     } else if (state.dataEnvrn->Month == 12 && state.dataEnvrn->DayOfMonth == 21) {
   11573        73882 :         if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
   11574          472 :             RepCol = state.dataOutRptPredefined->pdchSlfDec21_9;
   11575        73410 :         } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
   11576          472 :             RepCol = state.dataOutRptPredefined->pdchSlfDec21_12;
   11577        72938 :         } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
   11578          472 :             RepCol = state.dataOutRptPredefined->pdchSlfDec21_15;
   11579              :         }
   11580              :     }
   11581       249964 :     if (RepCol != 0) {
   11582         9936 :         for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   11583         8520 :             auto &surf = s_surf->Surface(SurfNum);
   11584         8520 :             if (surf.Class == SurfaceClass::Window) {
   11585           24 :                 PreDefTableEntry(state, RepCol, surf.Name, s_surf->SurfSunlitFrac(SurfNum));
   11586              :             }
   11587              :         }
   11588              :     }
   11589       249964 : }
   11590              : 
   11591           26 : void ReportSurfaceErrors(EnergyPlusData &state)
   11592              : {
   11593              : 
   11594              :     // SUBROUTINE INFORMATION:
   11595              :     //       AUTHOR         Linda Lawrie
   11596              :     //       DATE WRITTEN   November 2004
   11597              :     //       MODIFIED       na
   11598              :     //       RE-ENGINEERED  na
   11599              : 
   11600              :     // PURPOSE OF THIS SUBROUTINE:
   11601              :     // This subroutine reports some recurring type errors that can get mixed up with more important
   11602              :     // errors in the error file.
   11603              : 
   11604              :     using namespace DataErrorTracking; // for error tracking
   11605              : 
   11606           26 :     static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
   11607              : 
   11608              :     int Loop1;
   11609              :     int Loop2;
   11610              :     int Count;
   11611              :     int TotCount;
   11612           26 :     Array1D_bool SurfErrorReported;
   11613           26 :     Array1D_bool SurfErrorReported2;
   11614              : 
   11615           26 :     auto &s_surf = state.dataSurface;
   11616              : 
   11617           26 :     if (state.dataSolarShading->NumTooManyFigures + state.dataSolarShading->NumTooManyVertices + state.dataSolarShading->NumBaseSubSurround > 0) {
   11618            0 :         ShowMessage(state, "");
   11619            0 :         ShowMessage(state, "===== Recurring Surface Error Summary =====");
   11620            0 :         ShowMessage(state, "The following surface error messages occurred.");
   11621            0 :         ShowMessage(state, "");
   11622              : 
   11623            0 :         if (state.dataSolarShading->NumBaseSubSurround > 0) {
   11624            0 :             ShowMessage(state, "Base Surface does not surround subsurface errors occurring...");
   11625            0 :             ShowMessage(state,
   11626              :                         "Check that the GlobalGeometryRules object is expressing the proper starting corner and "
   11627              :                         "direction [CounterClockwise/Clockwise]");
   11628            0 :             ShowMessage(state, "");
   11629              :         }
   11630              : 
   11631            0 :         SurfErrorReported.dimension(s_surf->TotSurfaces, false);
   11632            0 :         TotCount = 0;
   11633            0 :         for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumBaseSubSurround; ++Loop1) {
   11634            0 :             Count = 0;
   11635            0 :             if (SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1)) {
   11636            0 :                 continue;
   11637              :             }
   11638            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
   11639            0 :                 if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
   11640            0 :                         state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
   11641            0 :                     state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
   11642            0 :                     ++Count;
   11643              :                 }
   11644              :             }
   11645            0 :             TotCount += Count;
   11646            0 :             state.dataErrTracking->TotalWarningErrors += Count - 1;
   11647            0 :             ShowWarningError(state,
   11648            0 :                              format("Base surface does not surround subsurface (CHKSBS), Overlap Status={}",
   11649            0 :                                     state.dataSolarShading->cOverLapStatus(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex)));
   11650            0 :             ShowContinueError(state, format("  The base surround errors occurred {} times.", Count));
   11651            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
   11652            0 :                 if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
   11653            0 :                         state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
   11654            0 :                     state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
   11655            0 :                     ShowContinueError(state,
   11656            0 :                                       format("Surface \"{}\" {} SubSurface \"{}\"",
   11657            0 :                                              s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1).Name,
   11658            0 :                                              MSG(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex),
   11659            0 :                                              s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex2).Name));
   11660              :                 }
   11661              :             }
   11662            0 :             SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1) = true;
   11663              :         }
   11664            0 :         if (TotCount > 0) {
   11665            0 :             ShowMessage(state, "");
   11666            0 :             ShowContinueError(state, format("  The base surround errors occurred {} times (total).", TotCount));
   11667            0 :             ShowMessage(state, "");
   11668              :         }
   11669              : 
   11670            0 :         SurfErrorReported2.allocate(s_surf->TotSurfaces);
   11671            0 :         SurfErrorReported = false;
   11672            0 :         TotCount = 0;
   11673            0 :         if (state.dataSolarShading->NumTooManyVertices > 0) {
   11674            0 :             ShowMessage(state, format("Too many vertices [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCV));
   11675            0 :             ShowMessage(state,
   11676              :                         "These occur throughout the year and may occur several times for the same surfaces. You "
   11677              :                         "may be able to reduce them by "
   11678              :                         "adding Output:Diagnostics,DoNotMirrorDetachedShading;");
   11679              :         }
   11680            0 :         for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyVertices; ++Loop1) {
   11681            0 :             Count = 0;
   11682            0 :             SurfErrorReported2 = false;
   11683            0 :             if (SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1)) {
   11684            0 :                 continue;
   11685              :             }
   11686            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
   11687            0 :                 if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
   11688            0 :                     state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
   11689            0 :                     ++Count;
   11690              :                 }
   11691              :             }
   11692            0 :             TotCount += Count;
   11693            0 :             state.dataErrTracking->TotalWarningErrors += Count - 1;
   11694            0 :             ShowMessage(state, "");
   11695            0 :             ShowWarningError(state, format("Too many vertices [>={}] in a shadow overlap", state.dataSolarShading->MaxHCV));
   11696            0 :             ShowContinueError(state,
   11697            0 :                               format("Overlapping figure={}, Surface Class=[{}]",
   11698            0 :                                      s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Name,
   11699            0 :                                      cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Class)));
   11700            0 :             ShowContinueError(state, format("  This error occurred {} times.", Count));
   11701            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
   11702            0 :                 if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
   11703            0 :                     state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
   11704            0 :                     if (SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2)) {
   11705            0 :                         continue;
   11706              :                     }
   11707            0 :                     ShowContinueError(state,
   11708            0 :                                       format("Figure being Overlapped={}, Surface Class=[{}]",
   11709            0 :                                              s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Name,
   11710            0 :                                              cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Class)));
   11711            0 :                     SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2) = true;
   11712              :                 }
   11713              :             }
   11714            0 :             SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1) = true;
   11715              :         }
   11716            0 :         if (TotCount > 0) {
   11717            0 :             ShowMessage(state, "");
   11718            0 :             ShowContinueError(state, format("  The too many vertices errors occurred {} times (total).", TotCount));
   11719            0 :             ShowMessage(state, "");
   11720              :         }
   11721              : 
   11722            0 :         SurfErrorReported = false;
   11723            0 :         TotCount = 0;
   11724            0 :         if (state.dataSolarShading->NumTooManyFigures > 0) {
   11725            0 :             ShowMessage(state, format("Too many figures [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCS));
   11726            0 :             ShowMessage(state,
   11727              :                         "These occur throughout the year and may occur several times for the same surfaces. You "
   11728              :                         "may be able to reduce them by "
   11729              :                         "adding OutputDiagnostics,DoNotMirrorDetachedShading;");
   11730              :         }
   11731            0 :         for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyFigures; ++Loop1) {
   11732            0 :             Count = 0;
   11733            0 :             SurfErrorReported2 = false;
   11734            0 :             if (SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1)) {
   11735            0 :                 continue;
   11736              :             }
   11737            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
   11738            0 :                 if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
   11739            0 :                     ++Count;
   11740              :                 }
   11741              :             }
   11742            0 :             TotCount += Count;
   11743            0 :             state.dataErrTracking->TotalWarningErrors += Count - 1;
   11744            0 :             ShowMessage(state, "");
   11745            0 :             ShowWarningError(state, format("Too many figures [>={}] in a shadow overlap", state.dataSolarShading->MaxHCS));
   11746            0 :             ShowContinueError(state,
   11747            0 :                               format("Overlapping figure={}, Surface Class=[{}]",
   11748            0 :                                      s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Name,
   11749            0 :                                      cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Class)));
   11750            0 :             ShowContinueError(state, format("  This error occurred {} times.", Count));
   11751            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
   11752            0 :                 if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
   11753            0 :                     if (SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2)) {
   11754            0 :                         continue;
   11755              :                     }
   11756            0 :                     ShowContinueError(state,
   11757            0 :                                       format("Figure being Overlapped={}, Surface Class=[{}]",
   11758            0 :                                              s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Name,
   11759            0 :                                              cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Class)));
   11760            0 :                     SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2) = true;
   11761              :                 }
   11762              :             }
   11763            0 :             SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1) = true;
   11764              :         }
   11765            0 :         if (TotCount > 0) {
   11766            0 :             ShowMessage(state, "");
   11767            0 :             ShowContinueError(state, format("  The too many figures errors occurred {} times (total).", TotCount));
   11768            0 :             ShowMessage(state, "");
   11769              :         }
   11770            0 :         SurfErrorReported.deallocate();
   11771            0 :         SurfErrorReported2.deallocate();
   11772              :     }
   11773           26 : }
   11774              : 
   11775          114 : void ComputeWinShadeAbsorpFactors(EnergyPlusData &state)
   11776              : {
   11777              : 
   11778              :     // SUBROUTINE INFORMATION:
   11779              :     //       AUTHOR         Fred Winkelmann
   11780              :     //       DATE WRITTEN   Mar 2001
   11781              :     //       MODIFIED       Oct 2002,FCW: change ConstrNumSh =
   11782              :     //       WindowShadingControl(WinShadeCtrlNum)%ShadedConstruction
   11783              :     //                      to Surface(SurfNum)%ShadedConstruction
   11784              :     //       RE-ENGINEERED  na
   11785              : 
   11786              :     // PURPOSE OF THIS SUBROUTINE:
   11787              :     // Called by InitSolarCalculations. Finds fractions that apportion radiation absorbed by a
   11788              :     // window shade to the two faces of the shade. For radiation incident from the left,
   11789              :     // ShadeAbsFacFace(1) is the fraction of radiation absorbed in the left-hand half of the
   11790              :     // of the shade and ShadeAbsFacFace(2) is the fraction absorbed in the right-hand half.
   11791              :     // The shade is assumed to be homogeneous.
   11792              : 
   11793              :     // REFERENCES: See EnergyPlus engineering documentation
   11794              :     // USE STATEMENTS: na
   11795          114 :     auto &s_mat = state.dataMaterial;
   11796          114 :     auto &s_surf = state.dataSurface;
   11797              : 
   11798          247 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   11799          283 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   11800          150 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   11801          150 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   11802          150 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   11803          206 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
   11804           56 :                 auto &surf = s_surf->Surface(SurfNum);
   11805           56 :                 if (surf.Class == SurfaceClass::Window && surf.HasShadeControl) {
   11806            8 :                     int WinShadeCtrlNum = surf.activeWindowShadingControl; // Window shading control number
   11807              : 
   11808            8 :                     int MatNumSh = 0;       // Shade layer material number
   11809            8 :                     Real64 AbsorpEff = 0.0; // Effective absorptance of isolated shade layer (fraction of
   11810              :                     //  of incident radiation remaining after reflected portion is
   11811              :                     //  removed that is absorbed
   11812            8 :                     if (ANY_SHADE(s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType)) {
   11813            0 :                         int const ConstrNumSh = surf.activeShadedConstruction;                 // Window construction number with shade
   11814            0 :                         int TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers; // Total layers in a construction
   11815              : 
   11816            0 :                         if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::IntShade) {
   11817            0 :                             MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay); // Interior shade
   11818            0 :                         } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::ExtShade) {
   11819            0 :                             MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1); // Exterior shade
   11820            0 :                         } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::BGShade) {
   11821            0 :                             if (state.dataConstruction->Construct(ConstrNumSh).TotGlassLayers == 2) {
   11822              :                                 // Double pane with between-glass shade
   11823            0 :                                 MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(3);
   11824              :                             } else {
   11825              :                                 // Triple pane with between-glass shade
   11826            0 :                                 MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(5);
   11827              :                             }
   11828              :                         }
   11829              : 
   11830            0 :                         auto const *matSh = s_mat->materials(MatNumSh);
   11831            0 :                         auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
   11832            0 :                         assert(matFenSh != nullptr);
   11833            0 :                         AbsorpEff = matFenSh->AbsorpSolar / (matFenSh->AbsorpSolar + matFenSh->Trans + 0.0001);
   11834            0 :                         AbsorpEff = min(max(AbsorpEff, 0.0001),
   11835              :                                         0.999); // Constrain to avoid problems with following log eval
   11836            0 :                         s_surf->SurfWinShadeAbsFacFace1(SurfNum) = (1.0 - std::exp(0.5 * std::log(1.0 - AbsorpEff))) / AbsorpEff;
   11837            0 :                         s_surf->SurfWinShadeAbsFacFace2(SurfNum) = 1.0 - s_surf->SurfWinShadeAbsFacFace1(SurfNum);
   11838              :                     }
   11839              :                 }
   11840              :             }
   11841          133 :         }
   11842              :     }
   11843          114 : }
   11844              : 
   11845        71220 : void CalcWinTransDifSolInitialDistribution(EnergyPlusData &state)
   11846              : {
   11847              : 
   11848              :     // SUBROUTINE INFORMATION:
   11849              :     //       AUTHOR         Rob Hitchcock
   11850              :     //       DATE WRITTEN   July 2007
   11851              :     //       MODIFIED       N/A
   11852              :     //       RE-ENGINEERED  N/A
   11853              : 
   11854              :     // PURPOSE OF THIS SUBROUTINE:
   11855              :     // This subroutine calculates the initial distribution
   11856              :     // of diffuse solar transmitted through exterior windows
   11857              :     // to individual heat transfer surfaces in each zone(or enclosure).
   11858              : 
   11859              :     // METHODOLOGY EMPLOYED:
   11860              :     // Apportions diffuse solar transmitted through each exterior window
   11861              :     // that is then absorbed, reflected, and/or transmitted
   11862              :     // by other heat transfer surfaces in the zone.
   11863              :     // Calculations use:
   11864              :     // 1. WinDifSolar calculated in SUBROUTINE CalcInteriorSolarDistribution,
   11865              :     // 2. view factors between each exterior window and
   11866              :     // other heat transfer surfaces in a zone
   11867              :     // calculated in SUBROUTINE CalcApproximateViewFactors, and
   11868              :     // 3. surface absorptances, reflectances, and transmittances
   11869              :     // determined here using revised code from SUBROUTINE InitIntSolarDistribution
   11870              : 
   11871              :     // Using/Aliasing
   11872              :     using namespace DataViewFactorInformation;
   11873              :     using namespace DataWindowEquivalentLayer;
   11874              : 
   11875              :     Real64 AbsInt;               // Tmp var for Inside surface short-wave absorptance
   11876              :     Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
   11877              :     Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
   11878              :     int BlNum;                   // Blind number
   11879              :     Real64 BlAbsDiffBk;          // Glass layer back diffuse solar absorptance when blind in place
   11880              :     Real64 AbsDiffBkBl;          // Blind diffuse back solar absorptance as part of glazing system
   11881              : 
   11882              :     //  REAL(r64)    :: DividerSolAbs      ! Window divider solar absorptance
   11883              :     //  REAL(r64)    :: DividerSolRefl     ! Window divider solar reflectance
   11884              :     //  INTEGER :: MatNumGl           ! Glass layer material number
   11885              :     //  INTEGER :: MatNumSh           ! Shade layer material number
   11886              :     //  REAL(r64)    :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
   11887              : 
   11888        71220 :     Real64 ViewFactor = 0.0;       // temp var for view factor
   11889              :                                    //        Real64 ViewFactorTotal;             // debug var for view factor total
   11890        71220 :     Real64 WinDifSolarTrans = 0.0; // debug var for WinDifSolar() [W]
   11891              :                                    //        Real64 WinDifSolarDistTotl;         // debug var for window total
   11892              :                                    //        distributed diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl; // debug
   11893              :                                    //        var for individual exterior window total distributed
   11894              :                                    //    diffuse solar absorbed [W]
   11895              :                                    //        Real64 WinDifSolarDistReflectedTotl; // debug var for individual exterior window total distributed
   11896              :                                    //    diffuse solar reflected [W]
   11897              :                                    //        Real64 WinDifSolarDistTransmittedTotl; // debug var for individual exterior window total distributed
   11898              :                                    //    diffuse solar transmitted [W]
   11899        71220 :     Real64 WinDifSolLayAbsW = 0.0; // temp var for diffuse solar absorbed by individual glass layer [W]
   11900              :                                    //        Real64 ZoneDifSolarTrans;               // debug var for WinDifSolar() [W]
   11901              :                                    //        Real64 ZoneDifSolarDistTotl;            // debug var for zone total
   11902              :                                    //        distributed diffuse solar [W] Real64 ZoneDifSolarDistAbsorbedTotl;    //
   11903              :                                    //        debug var for zone total distributed diffuse solar absorbed [W] Real64
   11904              :                                    //        ZoneDifSolarDistReflectedTotl;   // debug var for zone total distributed
   11905              :                                    //        diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl; //
   11906              :                                    //        debug var for zone total distributed diffuse solar transmitted [W]
   11907              : 
   11908        71220 :     Real64 DifSolarAbsW = 0.0;     // temp var for diffuse solar absorbed by surface [W]
   11909        71220 :     Real64 DifSolarAbs = 0.0;      // temp var for diffuse solar absorbed by surface [W/m2]
   11910        71220 :     Real64 DifSolarReflW = 0.0;    // temp var for diffuse solar reflected by surface [W]
   11911        71220 :     Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
   11912              : 
   11913        71220 :     Array2D<Real64> SurfWinAbsSolBeamEQL(2, CFSMAXNL + 1); // absorbed exterior beam radiation by layers fraction
   11914              :     Array2D<Real64> SurfWinAbsSolDiffEQL(2,
   11915        71220 :                                          CFSMAXNL + 1);        // absorbed exterior diffuse radiation by layers fraction
   11916        71220 :     Array2D<Real64> SurfWinAbsSolBeamBackEQL(2, CFSMAXNL + 1); // absorbed interior beam radiation by layers fraction from back
   11917        71220 :     Array2D<Real64> AbsSolDiffBackEQL(2, CFSMAXNL + 1);        // absorbed exterior diffuse radiation by layers fraction from back
   11918              :     int EQLNum;                                                // equivalent layer fenestration index
   11919              :     int Lay;                                                   // equivalent layer fenestration layer index
   11920              : 
   11921        71220 :     auto &s_surf = state.dataSurface;
   11922              : 
   11923              :     // Init accumulators for absorbed diffuse solar for all surfaces for later heat balance calcs
   11924        71220 :     state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs = 0.0;
   11925        71220 :     state.dataHeatBal->SurfWinInitialDifSolwinAbs = 0.0;
   11926              : 
   11927              :     // Init accumulator for total reflected diffuse solar within each zone for interreflection calcs
   11928        71220 :     state.dataHeatBal->EnclSolInitialDifSolReflW = 0.0;
   11929              : 
   11930              :     // Init accumulator for transmitted diffuse solar for all surfaces for reporting
   11931        71220 :     state.dataHeatBalSurf->SurfWinInitialDifSolInTrans = 0.0;
   11932              : 
   11933              :     // Loop over all zones doing initial distribution of diffuse solar to interior heat transfer surfaces
   11934       176528 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
   11935       105308 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
   11936              :         // Init Zone accumulators for debugging
   11937              :         //            ZoneDifSolarTrans = 0.0;
   11938              :         //            ZoneDifSolarDistAbsorbedTotl = 0.0;
   11939              :         //            ZoneDifSolarDistReflectedTotl = 0.0;
   11940              :         //            ZoneDifSolarDistTransmittedTotl = 0.0;
   11941              :         // Loop over all diffuse solar transmitting surfaces (i.e., exterior windows and TDDs) in the current zone
   11942       716995 :         for (int const DifTransSurfNum : thisEnclosure.SurfacePtr) {
   11943              :             // Skip surfaces that are not exterior, except for TDD_Diffusers
   11944       611687 :             auto &difTransSurf = s_surf->Surface(DifTransSurfNum);
   11945       611687 :             if ((difTransSurf.ExtBoundCond != ExternalEnvironment) && (difTransSurf.ExtBoundCond != OtherSideCondModeledExt) &&
   11946       207689 :                 (difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser)) {
   11947       207689 :                 continue;
   11948              :             }
   11949              : 
   11950              :             // Do I need to do anything special for TDDs?
   11951              :             //                if ( SurfaceWindow( DifTransSurfNum ).OriginalClass == SurfaceClass::TDD_Diffuser )
   11952              :             //                {
   11953              :             //                }
   11954              : 
   11955              :             // Skip surfaces that are not exterior windows or TDD diffusers
   11956       403998 :             if (difTransSurf.Class != SurfaceClass::Window && difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser) {
   11957       372884 :                 continue;
   11958              :             }
   11959              : 
   11960              :             //----------------------------------------------------------------------------------------------------------
   11961              :             // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH EXTERIOR WINDOWS AND TDDS TO INTERIOR HEAT TRANSFER
   11962              :             // SURFACES
   11963              :             //----------------------------------------------------------------------------------------------------------
   11964              : 
   11965              :             // Init transmitted solar debug vars
   11966              :             //                ViewFactorTotal = 0.0;
   11967        31114 :             WinDifSolarTrans = s_surf->SurfWinDifSolar(DifTransSurfNum);
   11968              :             //                ZoneDifSolarTrans += WinDifSolarTrans;
   11969              : 
   11970              :             // Init Exterior Window accumulators for debugging
   11971              :             //                WinDifSolarDistAbsorbedTotl = 0.0;
   11972              :             //                WinDifSolarDistReflectedTotl = 0.0;
   11973              :             //                WinDifSolarDistTransmittedTotl = 0.0;
   11974              : 
   11975              :             // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
   11976       425000 :             for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
   11977              :                 // Skip surfaces that are not heat transfer surfaces
   11978              :                 // Skip tubular daylighting device domes
   11979       393886 :                 auto &surf = s_surf->Surface(HeatTransSurfNum);
   11980              : 
   11981       393886 :                 if (surf.Class == SurfaceClass::TDD_Dome) {
   11982            0 :                     continue;
   11983              :                 }
   11984              : 
   11985              :                 // View factor from current (sending) window DifTransSurfNum to current (receiving) surface
   11986              :                 // HeatTransSurfNum
   11987       393886 :                 int const HTenclosureSurfNum = surf.SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
   11988       393886 :                 int const enclosureNum = surf.SolarEnclIndex;           // index for EnclSolInfo
   11989              :                 int const DTenclSurfNum =
   11990       393886 :                     s_surf->Surface(DifTransSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
   11991              : 
   11992       393886 :                 ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, DTenclSurfNum);
   11993              :                 // debug ViewFactorTotal
   11994              :                 //                    ViewFactorTotal += ViewFactor; // debug
   11995              : 
   11996              :                 // Skip receiving surfaces with 0.0 view factor
   11997       393886 :                 if (ViewFactor <= 0.0) {
   11998        96750 :                     continue;
   11999              :                 }
   12000              : 
   12001       297136 :                 Real64 const WinDifSolarTrans_Factor(WinDifSolarTrans * ViewFactor);
   12002       297136 :                 Real64 const win_SwitchingFactor(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum));
   12003       297136 :                 Real64 const per_HTSurfaceArea(1.0 / surf.Area);
   12004              : 
   12005              :                 // Calculate diffuse solar from current exterior window absorbed and reflected by current heat
   12006              :                 // transfer surface And calculate transmitted diffuse solar to adjacent zones through interior
   12007              :                 // windows
   12008       297136 :                 int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
   12009       297136 :                 if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
   12010              : 
   12011              :                     // Determine the inside (back) diffuse solar absorptance
   12012              :                     // and reflectance of the current heat transfer surface
   12013       219812 :                     InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
   12014              :                     // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
   12015       219812 :                     InsideDifReflectance = 1.0 - InsideDifAbsorptance;
   12016              : 
   12017              :                     // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
   12018              :                     //    * view factor from current (sending) window DifTransSurfNum to current (receiving)
   12019              :                     //    surface HeatTransSurfNum
   12020              :                     //    * current surface inside solar absorptance
   12021       219812 :                     DifSolarAbsW = WinDifSolarTrans_Factor * InsideDifAbsorptance; // [W]
   12022              : 
   12023              :                     // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
   12024              :                     //                                 / current surface net area
   12025       219812 :                     DifSolarAbs = DifSolarAbsW * per_HTSurfaceArea;
   12026              : 
   12027              :                     // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
   12028       219812 :                     state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
   12029              : 
   12030              :                     // Reflected diffuse solar [W] = current window transmitted diffuse solar
   12031              :                     //    * view factor from current (sending) window DifTransSurfNum to current (receiving)
   12032              :                     //    surface HeatTransSurfNum
   12033              :                     //    * current window inside solar reflectance
   12034       219812 :                     DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
   12035              : 
   12036              :                     // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12037              :                     // interreflection calcs
   12038       219812 :                     state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   12039              : 
   12040              :                     // Accumulate Window and Zone total distributed diffuse solar to check for conservation of
   12041              :                     // energy For opaque surfaces all incident diffuse is either absorbed or reflected
   12042              : 
   12043              :                 } else { // Exterior or Interior Window
   12044        77324 :                     int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
   12045        77324 :                     int TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
   12046        77324 :                     WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
   12047              : 
   12048        77324 :                     if (s_surf->SurfWinWindowModelType(HeatTransSurfNum) != WindowModel::EQL) {
   12049        77322 :                         if (NOT_SHADED(ShadeFlag)) { // No window shading
   12050              :                             // Init accumulator for transmittance calc below
   12051        77322 :                             DifSolarAbsW = 0.0;
   12052              : 
   12053              :                             // Calc diffuse solar absorbed by all window glass layers
   12054              :                             // Note: I am assuming here that individual glass layer absorptances have been
   12055              :                             // corrected
   12056              :                             //       to account for layer by layer transmittance and reflection effects.
   12057       154686 :                             for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   12058              :                                 // Calc diffuse solar absorbed from the inside by each window glass layer [W]
   12059        77364 :                                 AbsInt = state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
   12060        77364 :                                 WinDifSolLayAbsW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
   12061              : 
   12062              :                                 // Accumulate distributed diffuse solar absorbed [W] by overall window for
   12063              :                                 // transmittance calc below
   12064        77364 :                                 DifSolarAbsW += WinDifSolLayAbsW;
   12065              : 
   12066              :                                 // Accumulate diffuse solar absorbed from the inside by each window glass layer
   12067              :                                 // [W/m2] for heat balance calcs
   12068        77364 :                                 state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
   12069              :                             }
   12070              : 
   12071              :                             // Calc diffuse solar reflected back to zone
   12072              :                             // I don't really care if this is a window or opaque surface since I am just
   12073              :                             // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
   12074              :                             // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
   12075              :                             //    * view factor from current (sending) window DifTransSurfNum to current
   12076              :                             //    (receiving) surface HeatTransSurfNum
   12077              :                             //    * current window inside solar reflectance
   12078        77322 :                             InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   12079        77322 :                             DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   12080              : 
   12081              :                             // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12082              :                             // interreflection calcs
   12083        77322 :                             state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   12084              : 
   12085              :                             //------------------------------------------------------------------------------
   12086              :                             // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
   12087              :                             //------------------------------------------------------------------------------
   12088              : 
   12089              :                             // If this receiving window surface (HeatTransSurfNum) is an interior window,
   12090              :                             // calc distributed solar transmitted to adjacent zone [W]
   12091              :                             // NOTE: This calc is here because interior windows are currently assumed to have no
   12092              :                             // shading
   12093              : 
   12094              :                             // Get the adjacent surface number for this receiving window surface
   12095        77322 :                             int AdjSurfNum = surf.ExtBoundCond;
   12096              :                             // If the adjacent surface number is > 0, this is an interior window
   12097        77322 :                             if (AdjSurfNum > 0) { // this is an interior window surface
   12098              : 
   12099              :                                 // Calc diffuse solar from current exterior window
   12100              :                                 // transmitted through this interior window to adjacent zone [W]
   12101              :                                 // Transmitted diffuse solar [W] = current exterior window transmitted diffuse
   12102              :                                 // solar
   12103              :                                 //    * view factor from current (sending) window DifTransSurfNum to current
   12104              :                                 //    (receiving) surface HeatTransSurfNum
   12105              :                                 //    - diffuse absorbed by this interior window
   12106              :                                 //    - diffuse reflected by this interior window
   12107            0 :                                 Real64 DifSolarTransThroughW = WinDifSolarTrans_Factor - DifSolarAbsW - DifSolarReflW;
   12108              :                                 // HERE 8/15/07 Note Construct(AdjConstrNum)%TransDiff could be used here since
   12109              :                                 // the "front" transmittance for an interior window in the adjacent zone is the
   12110              :                                 // correct direction as long as I use the Construct() of the Surface in the
   12111              :                                 // adjacent zone. However, the above calculation better conserves energy, although
   12112              :                                 // possibly at the expense of less accurate transmittance calcs. Preliminary tests
   12113              :                                 // showed fairly good agreement between the two DifSolarTransW calculation
   12114              :                                 // methods, but for consistency I stuck with the above. int AdjConstrNum =
   12115              :                                 // Surface(AdjSurfNum).Construction;
   12116              :                                 //              DifSolarTransW = WinDifSolar(DifTransSurfNum) &
   12117              :                                 //                                * ViewFactor &
   12118              :                                 //                                * Construct(AdjConstrNum)%TransDiff
   12119              : 
   12120              :                                 // Get the adjacent zone index
   12121            0 :                                 int const adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
   12122              : 
   12123              :                                 // Call routine to distribute diffuse solar transmitted through this interior
   12124              :                                 // window into adjacent zone
   12125            0 :                                 CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransThroughW);
   12126              :                             }
   12127              : 
   12128              :                             // Calc transmitted Window and Zone total distributed diffuse solar to check for
   12129              :                             // conservation of energy This is not very effective since it assigns whatever
   12130              :                             // distributed diffuse solar has not been absorbed or reflected to transmitted.
   12131              :                             // Should be just total less reflected
   12132        77322 :                             Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   12133              : 
   12134              :                             // Accumulate transmitted diffuse solar for reporting
   12135        77322 :                             state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   12136              : 
   12137            0 :                         } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
   12138              :                             // Init accumulator for transmittance calc below
   12139            0 :                             DifSolarAbsW = 0.0;
   12140              : 
   12141            0 :                             auto const &construct = state.dataConstruction->Construct(ConstrNum);
   12142            0 :                             auto const &construct_AbsDiffBack = construct.AbsDiffBack;
   12143            0 :                             auto const &construct_sh = state.dataConstruction->Construct(ConstrNumSh);
   12144            0 :                             auto const &construct_sh_AbsDiffBack = construct_sh.AbsDiffBack;
   12145            0 :                             for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   12146              :                                 // Calc diffuse solar absorbed in each window glass layer
   12147            0 :                                 WinDifSolLayAbsW =
   12148              :                                     WinDifSolarTrans_Factor *
   12149            0 :                                     Window::InterpSw(win_SwitchingFactor, construct_AbsDiffBack(IGlass), construct_sh_AbsDiffBack(IGlass));
   12150              : 
   12151              :                                 // Accumulate distributed diffuse solar absorbed [W] by overall window for
   12152              :                                 // transmittance calc below
   12153            0 :                                 DifSolarAbsW += WinDifSolLayAbsW;
   12154              : 
   12155              :                                 // Accumulate diffuse solar absorbed from the inside by each window glass layer
   12156              :                                 // [W/m2] for heat balance calcs
   12157            0 :                                 state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
   12158              :                             }
   12159              : 
   12160              :                             // Calc diffuse solar reflected back to zone
   12161            0 :                             DifSolarReflW = WinDifSolarTrans_Factor *
   12162            0 :                                             Window::InterpSw(win_SwitchingFactor, construct.ReflectSolDiffBack, construct_sh.ReflectSolDiffBack);
   12163              : 
   12164              :                             // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12165              :                             // interreflection calcs
   12166            0 :                             state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   12167              : 
   12168              :                             // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12169              :                             // conservation of energy This is not very effective since it assigns whatever
   12170              :                             // distributed diffuse solar has not been absorbed or reflected to transmitted.
   12171              :                             // Should be just total less reflected
   12172            0 :                             Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   12173              : 
   12174              :                             // Accumulate transmitted diffuse solar for reporting
   12175            0 :                             state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   12176              : 
   12177            0 :                         } else if (ConstrNumSh != 0) {
   12178              :                             // Interior, exterior or between-glass shade, screen or blind in place
   12179              : 
   12180              :                             // Init accumulator for transmittance calc below
   12181            0 :                             DifSolarAbsW = 0.0;
   12182            0 :                             WinDifSolLayAbsW = 0.0;
   12183              : 
   12184              :                             // First calc diffuse solar absorbed by each glass layer in this window with
   12185              :                             // shade/blind in place
   12186            0 :                             auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
   12187            0 :                             auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
   12188            0 :                             Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12189              : 
   12190            0 :                             for (int IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
   12191            0 :                                 if (ANY_SHADE_SCREEN(ShadeFlag)) {
   12192              :                                     // Calc diffuse solar absorbed in each window glass layer and shade
   12193            0 :                                     WinDifSolLayAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBack(IGlass);
   12194            0 :                                 } else if (ANY_BLIND(ShadeFlag)) {
   12195            0 :                                     auto const &slatDfAbsLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
   12196            0 :                                     auto const &slatDfAbsHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
   12197            0 :                                     BlAbsDiffBk = Interp(slatDfAbsLo.Sol.Bk.Df.Abs, slatDfAbsHi.Sol.Bk.Df.Abs, slatInterpFac);
   12198              :                                     // Calc diffuse solar absorbed in each window glass layer and shade
   12199            0 :                                     WinDifSolLayAbsW = WinDifSolarTrans_Factor * BlAbsDiffBk;
   12200              :                                 }
   12201              : 
   12202              :                                 // Accumulate distributed diffuse solar absorbed [W] by overall window for
   12203              :                                 // transmittance calc below
   12204            0 :                                 DifSolarAbsW += WinDifSolLayAbsW;
   12205              : 
   12206              :                                 // Accumulate diffuse solar absorbed from the inside by each window glass layer
   12207              :                                 // [W/m2] for heat balance calcs
   12208            0 :                                 state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
   12209              :                             }
   12210              : 
   12211              :                             // Next calc diffuse solar reflected back to zone from window with shade or blind on
   12212              :                             // Diffuse back solar reflectance, bare glass or shade on
   12213            0 :                             InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   12214            0 :                             if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
   12215            0 :                                 auto const &constr = state.dataConstruction->Construct(ConstrNum);
   12216            0 :                                 auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12217            0 :                                 auto const &btarSlatLo = constr.blindTARs[surfShade.blind.slatAngIdxLo];
   12218            0 :                                 auto const &btarSlatHi = constr.blindTARs[surfShade.blind.slatAngIdxHi];
   12219            0 :                                 Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12220              :                                 // Diffuse back solar reflectance, blind present, vs. slat angle
   12221            0 :                                 InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
   12222              :                             }
   12223            0 :                             DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
   12224              : 
   12225              :                             // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12226              :                             // interreflection calcs
   12227            0 :                             state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   12228              : 
   12229              :                             // Now calc diffuse solar absorbed by shade/blind itself
   12230            0 :                             BlNum = surfShade.blind.matNum;
   12231            0 :                             if (ANY_SHADE_SCREEN(ShadeFlag)) {
   12232              :                                 // Calc diffuse solar absorbed by shade or screen [W]
   12233            0 :                                 ShBlDifSolarAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBackShade;
   12234            0 :                             } else if (ANY_BLIND(ShadeFlag)) {
   12235            0 :                                 auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12236            0 :                                 auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
   12237            0 :                                 auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
   12238            0 :                                 Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12239            0 :                                 AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
   12240            0 :                                 ShBlDifSolarAbsW = WinDifSolarTrans_Factor * AbsDiffBkBl;
   12241              :                             }
   12242              :                             // Correct for divider shadowing
   12243            0 :                             if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
   12244            0 :                                 ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
   12245              :                             }
   12246              : 
   12247              :                             // Accumulate diffuse solar absorbed  by shade or screen [W/m2] for heat balance calcs
   12248            0 :                             s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += ShBlDifSolarAbsW * per_HTSurfaceArea;
   12249              : 
   12250              :                             // Accumulate distributed diffuse solar absorbed [W] by overall window for
   12251              :                             // transmittance calc below
   12252            0 :                             DifSolarAbsW += ShBlDifSolarAbsW;
   12253              : 
   12254              :                             // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12255              :                             // conservation of energy This is not very effective since it assigns whatever
   12256              :                             // distributed diffuse solar has not been absorbed or reflected to transmitted.
   12257              :                             // Should be just total less reflected
   12258            0 :                             Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   12259              : 
   12260              :                             // Accumulate transmitted diffuse solar for reporting
   12261            0 :                             state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   12262              :                         } // End of shading flag check
   12263              : 
   12264              :                     } else {
   12265              :                         // SurfaceWindow(HeatTransSurfNum)%WindowModelType == WindowModel:: EQL
   12266              :                         // ConstrNum=Surface(HeatTransSurfNum)%Construction
   12267              :                         // call the ASHWAT fenestration model for diffuse radiation here
   12268            2 :                         WindowEquivalentLayer::CalcEQLOpticalProperty(state, HeatTransSurfNum, SolarArrays::DIFF, AbsSolDiffBackEQL);
   12269              : 
   12270            2 :                         EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
   12271            6 :                         for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(EQLNum).NL; ++Lay) {
   12272              : 
   12273              :                             // Calc diffuse solar absorbed from the inside by each layer of EQL model [W]
   12274              :                             // WinDifSolLayAbsW = WinDifSolar(DifTransSurfNum)* ViewFactor *
   12275              :                             // Construct(ConstrNum)%AbsDiffBack(Lay)
   12276            4 :                             WinDifSolLayAbsW = WinDifSolarTrans_Factor * AbsSolDiffBackEQL(2, Lay);
   12277              : 
   12278              :                             // Accumulate distributed diffuse solar absorbed [W] by overall window for
   12279              :                             // transmittance calc below
   12280            4 :                             DifSolarAbsW += WinDifSolLayAbsW;
   12281              : 
   12282              :                             // Accumulate diffuse solar absorbed from the inside by each window layer [W/m2] for
   12283              :                             // heat balance calcs
   12284            4 :                             state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, Lay) += WinDifSolLayAbsW * per_HTSurfaceArea;
   12285              : 
   12286              :                             // ASHWAT equivalent layer model may require not the individual layer absorption but
   12287              :                             // the flux InitialDifSolwinEQL(HeatTransSurfNum) = WinDifSolar(DifTransSurfNum)*
   12288              :                             // ViewFactor
   12289              :                         }
   12290              : 
   12291              :                         // Calc diffuse solar reflected back to zone
   12292              :                         // I don't really care if this is a window or opaque surface since I am just
   12293              :                         // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
   12294              :                         // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
   12295              :                         //    * view factor from current (sending) window DifTransSurfNum to current (receiving)
   12296              :                         //    surface HeatTransSurfNum
   12297              :                         //    * current window inside solar reflectance
   12298            2 :                         InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   12299            2 :                         DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   12300              : 
   12301              :                         // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12302              :                         // interreflection calcs
   12303            2 :                         state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   12304              : 
   12305              :                         //------------------------------------------------------------------------------
   12306              :                         // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
   12307              :                         //------------------------------------------------------------------------------
   12308              : 
   12309              :                         // If this receiving window surface (HeatTransSurfNum) is an interior window,
   12310              :                         // calc distributed solar transmitted to adjacent zone [W]
   12311              :                         // NOTE: This calc is here because interior windows are currently assumed to have no
   12312              :                         // shading
   12313              : 
   12314              :                         // Get the adjacent surface number for this receiving window surface
   12315            2 :                         int const AdjSurfNum = s_surf->Surface(HeatTransSurfNum).ExtBoundCond;
   12316              :                         // If the adjacent surface number is > 0, this is an interior window
   12317            2 :                         if (AdjSurfNum > 0) { // this is an interior window surface
   12318              : 
   12319              :                             // Calc diffuse solar from current exterior window
   12320              :                             // transmitted through this interior window to adjacent zone [W]
   12321              :                             // Transmitted diffuse solar [W] = current exterior window transmitted diffuse solar
   12322              :                             //    * view factor from current (sending) window DifTransSurfNum to current
   12323              :                             //    (receiving) surface HeatTransSurfNum
   12324            0 :                             Real64 DifSolarTransW = AbsSolDiffBackEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1) * ViewFactor;
   12325              :                             // int AdjConstrNum = Surface(AdjSurfNum).Construction;
   12326              :                             // Get the adjacent zone index
   12327            0 :                             int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
   12328              :                             // Call routine to distribute diffuse solar transmitted through this interior window
   12329              :                             // into adjacent zone
   12330            0 :                             CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransW);
   12331              :                         }
   12332              : 
   12333              :                         // Calc transmitted Window and Zone total distributed diffuse solar to check for
   12334              :                         // conservation of energy This is not very effective since it assigns whatever
   12335              :                         // distributed diffuse solar has not been absorbed or reflected to transmitted.
   12336              :                         // Should be just total less reflected
   12337            2 :                         Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   12338              : 
   12339              :                         // Accumulate transmitted diffuse solar for reporting
   12340            2 :                         state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   12341              : 
   12342              :                     } // IF (SurfaceWindow(HeatTransSurfNum)%WindowModelType /= WindowModel:: EQL) THEN
   12343              : 
   12344              :                     // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
   12345              :                     // I would need revised view factors that included these surface types.
   12346              :                     // By ignoring them here, the diffuse solar is accounted for on the other surfaces
   12347              : 
   12348              :                     //          IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN  ! Window has a frame
   12349              :                     // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
   12350              :                     //          END IF
   12351              : 
   12352              :                     //          IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN  ! Window has dividers
   12353              :                     //            DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
   12354              :                     //            IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended
   12355              :                     //            divider; account for inside glass
   12356              :                     //              MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
   12357              :                     //              TransGl = dataMaterial.Material(MatNumGl)%Trans
   12358              :                     //              ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
   12359              :                     //              AbsGl = 1.0d0-TransGl-ReflGl
   12360              :                     //              DividerSolRefl = 1.0d0-DividerSolAbs
   12361              :                     //              DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
   12362              :                     //              DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
   12363              :                     //            END IF
   12364              :                     // Correct for interior shade transmittance
   12365              :                     //            IF(ShadeFlag == IntShadeOn) THEN
   12366              :                     //              MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
   12367              :                     //              DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
   12368              :                     //            ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
   12369              :                     //              DividerSolAbs = DividerSolAbs *
   12370              :                     //              InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
   12371              :                     //                  SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
   12372              :                     //            END IF
   12373              :                     // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
   12374              : 
   12375              :                     //          END IF  ! Window has dividers
   12376              : 
   12377              :                 } // opaque or window heat transfer surface
   12378              : 
   12379              :             } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
   12380              : 
   12381              :             // Check debug var for view factors here
   12382              :             // ViewFactorTotal
   12383              :             // Check debug vars for individual transmitting surfaces here
   12384              :             //                WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
   12385              :             //                WinDifSolarDistTransmittedTotl;
   12386              :             // WinDifSolarTrans
   12387              : 
   12388              :         } // DifTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
   12389              : 
   12390              :         // Check debug vars for zone totals here
   12391              :         //            ZoneDifSolarDistTotl = ZoneDifSolarDistAbsorbedTotl + ZoneDifSolarDistReflectedTotl +
   12392              :         //            ZoneDifSolarDistTransmittedTotl;
   12393              :         // ZoneDifSolarTrans
   12394              :         // ZoneDifSolarDistAbsorbedTotl
   12395              :         // ZoneDifSolarDistReflectedTotl
   12396              :         // ZoneDifSolarDistTransmittedTotl
   12397              :         //    CALL DisplayString('Diffuse Solar Distribution Zone Totals')
   12398              : 
   12399              :     } // ZoneNum = 1, NumOfZones
   12400        71220 : }
   12401            0 : void CalcInteriorWinTransDifSolInitialDistribution(EnergyPlusData &state,
   12402              :                                                    int const IntWinEnclosureNum,     // Interior Window Enclosure index number
   12403              :                                                    int const IntWinSurfNum,          // Interior Window Surface number
   12404              :                                                    Real64 const IntWinDifSolarTransW // Diffuse Solar transmitted through Interior Window
   12405              :                                                                                      // IntWinSurfNum from adjacent enclosure [W]
   12406              : )
   12407              : {
   12408              : 
   12409              :     // SUBROUTINE INFORMATION:
   12410              :     //       AUTHOR         Rob Hitchcock
   12411              :     //       DATE WRITTEN   August 2007
   12412              :     //       MODIFIED       N/A
   12413              :     //       RE-ENGINEERED  N/A
   12414              : 
   12415              :     // PURPOSE OF THIS SUBROUTINE:
   12416              :     // This subroutine calculates the initial distribution
   12417              :     // of diffuse solar transmitted through the given interior window
   12418              :     // to individual heat transfer surfaces in the given enclosure.
   12419              :     // Diffuse solar transmitted through interior windows in this enclosure
   12420              :     // to adjacent enclosures, is added to the EnclSolInitialDifSolReflW
   12421              :     // of the adjacent enclosure for subsequent interreflection calcs
   12422              : 
   12423              :     // METHODOLOGY EMPLOYED:
   12424              :     // Similar to method used in CalcWinTransDifSolInitialDistribution.
   12425              :     // Apportions diffuse solar transmitted through an interior window
   12426              :     // that is then absorbed, reflected, and/or transmitted
   12427              :     // by other heat transfer surfaces in the given enclosure.
   12428              :     // Calculations use:
   12429              :     // 1. DifSolarTransW calculated in SUBROUTINE CalcWinTransDifSolInitialDistribution,
   12430              :     // 2. view factors between the interior window and
   12431              :     // other heat transfer surfaces in the given enclosure
   12432              :     // calculated in SUBROUTINE CalcApproximateViewFactors, and
   12433              :     // 3. surface absorptances, reflectances, and transmittances
   12434              :     // determined here using revised code from SUBROUTINE InitIntSolarDistribution
   12435              : 
   12436              :     // Using/Aliasing
   12437              :     using namespace DataViewFactorInformation;
   12438              : 
   12439              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   12440              :     int IGlass;                  // Glass layer counter
   12441              :     int TotGlassLayers;          // Number of glass layers in a window construction
   12442              :     WinShadingType ShadeFlag;    // Shading flag
   12443              :     Real64 AbsInt;               // Tmp var for Inside surface short-wave absorptance
   12444              :     Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
   12445              :     Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
   12446              :     int BlNum;                   // Blind number
   12447              :     Real64 BlAbsDiffBk;          // Glass layer back diffuse solar absorptance when blind in place
   12448              :     Real64 AbsDiffBkBl;          // Blind diffuse back solar absorptance as part of glazing system
   12449              : 
   12450              :     //  REAL(r64)    :: DividerSolAbs      ! Window divider solar absorptance
   12451              :     //  REAL(r64)    :: DividerSolRefl     ! Window divider solar reflectance
   12452              :     //  INTEGER :: MatNumGl           ! Glass layer material number
   12453              :     //  INTEGER :: MatNumSh           ! Shade layer material number
   12454              :     //  REAL(r64)    :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
   12455              : 
   12456              :     Real64 ViewFactor;       // temp var for view factor
   12457              :     Real64 ViewFactorTotal;  // debug var for view factor total
   12458              :     Real64 WinDifSolarTrans; // debug var for WinDifSolar() [W]
   12459              :                              //        Real64 WinDifSolarDistTotl; // debug var for window total distributed
   12460              :                              //        diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl( 0.0 ); // debug var
   12461              :                              //        for individual exterior window total
   12462              :                              // distributed
   12463              :     //           diffuse solar absorbed [W]
   12464              :     //        Real64 WinDifSolarDistReflectedTotl( 0.0 ); // debug var for individual exterior window total
   12465              :     //        distributed
   12466              :     //           diffuse solar reflected [W]
   12467              :     //        Real64 WinDifSolarDistTransmittedTotl( 0.0 ); // debug var for individual exterior window total
   12468              :     //        distributed
   12469              :     //           diffuse solar transmitted [W]
   12470              :     Real64 WinDifSolLayAbsW; // temp var for diffuse solar absorbed by individual glass layer [W]
   12471              :                              //        Real64 ZoneDifSolarTrans( 0.0 ); // debug var for WinDifSolar() [W]
   12472              :     //  REAL(r64)    :: ZoneDifSolarDistTotl    ! debug var for zone total distributed diffuse solar [W]
   12473              :     //        Real64 ZoneDifSolarDistAbsorbedTotl( 0.0 ); // debug var for zone total distributed diffuse solar
   12474              :     //        absorbed [W] Real64 ZoneDifSolarDistReflectedTotl( 0.0 ); // debug var for zone total distributed
   12475              :     //        diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl( 0.0 ); // debug var for zone
   12476              :     //        total distributed diffuse solar transmitted [W]
   12477              : 
   12478            0 :     Real64 DifSolarAbsW = 0.0;     // temp var for diffuse solar absorbed by surface [W]
   12479            0 :     Real64 DifSolarAbs = 0.0;      // temp var for diffuse solar absorbed by surface [W/m2]
   12480            0 :     Real64 DifSolarReflW = 0.0;    // temp var for diffuse solar reflected by surface [W]
   12481            0 :     Real64 DifSolarTransW = 0.0;   // temp var for diffuse solar transmitted through interior window surface [W]
   12482            0 :     Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
   12483              : 
   12484              :     //-------------------------------------------------------------------------------------------------
   12485              :     // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO INTERIOR HEAT TRANSFER SURFACES
   12486              :     //-------------------------------------------------------------------------------------------------
   12487              : 
   12488            0 :     auto &s_surf = state.dataSurface;
   12489              : 
   12490              :     // Init debug vars
   12491            0 :     ViewFactorTotal = 0.0;
   12492            0 :     WinDifSolarTrans = IntWinDifSolarTransW;
   12493              : 
   12494            0 :     auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(IntWinEnclosureNum);
   12495              :     // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
   12496            0 :     Real64 InitialZoneDifSolReflW_zone(0.0);
   12497            0 :     for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
   12498              : 
   12499            0 :         auto &surf = s_surf->Surface(HeatTransSurfNum);
   12500              : 
   12501              :         // Skip surfaces that are not heat transfer surfaces
   12502            0 :         if (!surf.HeatTransSurf) {
   12503            0 :             continue;
   12504              :         }
   12505              :         // Skip tubular daylighting device domes
   12506            0 :         if (surf.Class == SurfaceClass::TDD_Dome) {
   12507            0 :             continue;
   12508              :         }
   12509              : 
   12510              :         // View factor from current (sending) window IntWinSurfNum to current (receiving) surface HeatTransSurfNum
   12511            0 :         int HTenclosureSurfNum = surf.SolarEnclSurfIndex;                          // HT surface index for EnclSolInfo.SurfacePtr and F arrays
   12512            0 :         int enclosureNum = surf.SolarEnclIndex;                                    // index for EnclSolInfo
   12513            0 :         int IntWinEnclSurfNum = s_surf->Surface(IntWinSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
   12514              : 
   12515            0 :         ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, IntWinEnclSurfNum);
   12516              :         // debug ViewFactorTotal
   12517            0 :         ViewFactorTotal += ViewFactor; // debug
   12518              : 
   12519              :         // Skip receiving surfaces with 0.0 view factor
   12520            0 :         if (ViewFactor <= 0.0) {
   12521            0 :             continue;
   12522              :         }
   12523            0 :         Real64 const SolarTrans_ViewFactor(IntWinDifSolarTransW * ViewFactor);
   12524              : 
   12525              :         // Calculate diffuse solar from current interior window absorbed and reflected by current heat transfer
   12526              :         // surface And calculate transmitted diffuse solar to adjacent zones through interior windows
   12527            0 :         int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
   12528            0 :         if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
   12529              : 
   12530              :             // Determine the inside (back) diffuse solar absorptance
   12531              :             // and reflectance of the current heat transfer surface
   12532            0 :             InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
   12533              :             // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
   12534            0 :             InsideDifReflectance = 1.0 - InsideDifAbsorptance;
   12535              : 
   12536              :             // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
   12537              :             //    * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
   12538              :             //    HeatTransSurfNum
   12539              :             //    * current surface inside solar absorptance
   12540            0 :             DifSolarAbsW = SolarTrans_ViewFactor * InsideDifAbsorptance; // [W]
   12541              : 
   12542              :             // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
   12543              :             //                                 / current surface net area
   12544            0 :             DifSolarAbs = DifSolarAbsW / surf.Area;
   12545              : 
   12546              :             // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
   12547            0 :             state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
   12548              : 
   12549              :             // Reflected diffuse solar [W] = current window transmitted diffuse solar
   12550              :             //    * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
   12551              :             //    HeatTransSurfNum
   12552              :             //    * current window inside solar reflectance
   12553            0 :             DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
   12554              : 
   12555              :             // Accumulate total reflected distributed diffuse solar for each zone for subsequent interreflection
   12556              :             // calcs
   12557            0 :             InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12558              : 
   12559              :             // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12560              :             // For opaque surfaces all incident diffuse is either absorbed or reflected
   12561              :             //                WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
   12562              :             //                WinDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
   12563              :             //                ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
   12564              :             //                ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
   12565              : 
   12566              :         } else { // Exterior or Interior Window
   12567              : 
   12568            0 :             int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
   12569            0 :             auto const &construction = state.dataConstruction->Construct(ConstrNum);
   12570              : 
   12571            0 :             TotGlassLayers = construction.TotGlassLayers;
   12572            0 :             ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
   12573              : 
   12574            0 :             if (NOT_SHADED(ShadeFlag)) { // No window shading
   12575              :                 // Init accumulator for transmittance calc below
   12576            0 :                 DifSolarAbsW = 0.0;
   12577              : 
   12578              :                 // Calc diffuse solar absorbed by all window glass layers
   12579              :                 // Note: I am assuming here that individual glass layer absorptances have been corrected
   12580              :                 //       to account for layer by layer transmittance and reflection effects.
   12581            0 :                 for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   12582              :                     // Calc diffuse solar absorbed from the inside by each window glass layer [W]
   12583            0 :                     AbsInt = construction.AbsDiffBack(IGlass);
   12584            0 :                     WinDifSolLayAbsW = SolarTrans_ViewFactor * construction.AbsDiffBack(IGlass);
   12585              : 
   12586              :                     // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12587              :                     // below
   12588            0 :                     DifSolarAbsW += WinDifSolLayAbsW;
   12589              : 
   12590              :                     // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
   12591              :                     // heat balance calcs
   12592            0 :                     state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
   12593              :                 }
   12594              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12595              :                 //                    WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12596              :                 //                    ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12597              : 
   12598              :                 // Calc diffuse solar reflected back to zone
   12599              :                 // I don't really care if this is a window or opaque surface since I am just
   12600              :                 // accumulating all reflected diffuse solar in a zone bucket for "interreflected" distribution
   12601              :                 // Reflected diffuse solar [W] = current window transmitted diffuse solar
   12602              :                 //    * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
   12603              :                 //    HeatTransSurfNum
   12604              :                 //    * current window inside solar reflectance
   12605            0 :                 DifSolarReflW = SolarTrans_ViewFactor * construction.ReflectSolDiffBack;
   12606              : 
   12607              :                 // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12608              :                 // interreflection calcs
   12609            0 :                 InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12610              : 
   12611              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12612              : 
   12613              :                 //                    WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12614              :                 //                    ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12615              : 
   12616              :                 // Calc transmitted Window and Zone total distributed diffuse solar to check for conservation of
   12617              :                 // energy This is not very effective since it assigns whatever distributed diffuse solar has not
   12618              :                 // been absorbed or reflected to transmitted.
   12619            0 :                 DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
   12620              : 
   12621              :                 // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12622              :                 // conservation of energy
   12623              :                 //                    WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12624              :                 //                    ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12625              : 
   12626              :                 // Accumulate transmitted diffuse solar for reporting
   12627            0 :                 state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
   12628              : 
   12629              :                 //-----------------------------------------------------------------------------------
   12630              :                 // ADD TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
   12631              :                 // TOTAL REFLECTED DIFFUSE SOLAR FOR SUBSEQUENT INTERREFLECTION CALCS
   12632              :                 //-----------------------------------------------------------------------------------
   12633              : 
   12634              :                 // If this receiving window surface (HeatTransSurfNum) is an interior window,
   12635              :                 // add transmitted diffuse solar to adjacent zone total reflected distributed
   12636              :                 // diffuse solar for subsequent interreflection calcs
   12637              :                 // NOTE: This calc is here because interior windows are currently assumed to have no shading
   12638              : 
   12639              :                 // Get the adjacent surface number for this receiving window surface
   12640            0 :                 int const AdjSurfNum = surf.ExtBoundCond;
   12641              :                 // If the adjacent surface number is > 0, this is an interior window
   12642            0 :                 if (AdjSurfNum > 0) { // this is an interior window surface
   12643              : 
   12644              :                     // Get the adjacent zone/enclosure index
   12645              :                     // Add transmitted diffuse solar to total reflected distributed diffuse solar for each zone
   12646              :                     // for subsequent interreflection calcs
   12647            0 :                     state.dataHeatBal->EnclSolInitialDifSolReflW(s_surf->Surface(AdjSurfNum).SolarEnclIndex) += DifSolarTransW; // [W]
   12648              :                 }
   12649              : 
   12650            0 :             } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
   12651              :                 // Init accumulator for transmittance calc below
   12652            0 :                 auto const &constructionSh = state.dataConstruction->Construct(ConstrNumSh);
   12653            0 :                 DifSolarAbsW = 0.0;
   12654              : 
   12655            0 :                 for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   12656              :                     // Calc diffuse solar absorbed in each window glass layer
   12657            0 :                     WinDifSolLayAbsW = SolarTrans_ViewFactor * InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum),
   12658            0 :                                                                         construction.AbsDiffBack(IGlass),
   12659            0 :                                                                         constructionSh.AbsDiffBack(IGlass));
   12660              : 
   12661              :                     // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12662              :                     // below
   12663            0 :                     DifSolarAbsW += WinDifSolLayAbsW;
   12664              : 
   12665              :                     // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
   12666              :                     // heat balance calcs
   12667            0 :                     state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
   12668              :                 }
   12669              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12670              :                 //                                      WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12671              :                 //                                      ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12672              : 
   12673              :                 // Calc diffuse solar reflected back to zone
   12674            0 :                 DifSolarReflW =
   12675              :                     SolarTrans_ViewFactor *
   12676            0 :                     InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum), construction.ReflectSolDiffBack, constructionSh.ReflectSolDiffBack);
   12677              : 
   12678              :                 // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12679              :                 // interreflection calcs
   12680            0 :                 InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12681              : 
   12682              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12683              :                 //                                      WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12684              :                 //                                      ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12685              : 
   12686              :                 // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12687              :                 // conservation of energy This is not very effective since it assigns whatever distributed diffuse
   12688              :                 // solar has not been absorbed or reflected to transmitted.
   12689            0 :                 DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
   12690              :                 //                                      WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12691              :                 //                                      ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug
   12692              :                 //[W]
   12693              : 
   12694              :                 // Accumulate transmitted diffuse solar for reporting
   12695            0 :                 state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
   12696              : 
   12697              :             } else {
   12698            0 :                 auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
   12699              :                 // Interior, exterior or between-glass shade, screen or blind in place
   12700              : 
   12701              :                 // Init accumulator for transmittance calc below
   12702            0 :                 DifSolarAbsW = 0.0;
   12703            0 :                 WinDifSolLayAbsW = 0.0;
   12704              : 
   12705              :                 // First calc diffuse solar absorbed by each glass layer in this window with shade/blind in place
   12706            0 :                 auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
   12707            0 :                 for (IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
   12708            0 :                     if (ANY_SHADE_SCREEN(ShadeFlag)) {
   12709              :                         // Calc diffuse solar absorbed in each window glass layer and shade
   12710            0 :                         WinDifSolLayAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBack(IGlass);
   12711            0 :                     } else if (ANY_BLIND(ShadeFlag)) {
   12712            0 :                         auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12713            0 :                         auto const &dfAbsSlatLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
   12714            0 :                         auto const &dfAbsSlatHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
   12715            0 :                         Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12716            0 :                         BlAbsDiffBk = Interp(dfAbsSlatLo.Sol.Bk.Df.Abs, dfAbsSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
   12717              :                         // Calc diffuse solar absorbed in each window glass layer and shade
   12718            0 :                         WinDifSolLayAbsW = SolarTrans_ViewFactor * BlAbsDiffBk;
   12719              :                     }
   12720              : 
   12721              :                     // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12722              :                     // below
   12723            0 :                     DifSolarAbsW += WinDifSolLayAbsW;
   12724              : 
   12725              :                     // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
   12726              :                     // heat balance calcs
   12727            0 :                     state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
   12728              :                 }
   12729              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12730              :                 //                    WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12731              :                 //                    ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12732              : 
   12733              :                 // Next calc diffuse solar reflected back to zone from window with shade or blind on
   12734              :                 // Diffuse back solar reflectance, bare glass or shade on
   12735            0 :                 InsideDifReflectance = construction.ReflectSolDiffBack;
   12736            0 :                 if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
   12737            0 :                     auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12738            0 :                     auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
   12739            0 :                     auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
   12740            0 :                     Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12741              :                     // Diffuse back solar reflectance, blind present, vs. slat angle
   12742            0 :                     InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
   12743              :                 }
   12744            0 :                 DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
   12745              : 
   12746              :                 // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12747              :                 // interreflection calcs
   12748            0 :                 InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12749              : 
   12750              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12751              :                 //                    WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12752              :                 //                    ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12753              : 
   12754              :                 // Now calc diffuse solar absorbed by shade/blind itself
   12755            0 :                 BlNum = surfShade.blind.matNum;
   12756            0 :                 if (ANY_SHADE_SCREEN(ShadeFlag)) {
   12757              :                     // Calc diffuse solar absorbed by shade or screen [W]
   12758            0 :                     ShBlDifSolarAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBackShade;
   12759            0 :                 } else if (ANY_BLIND(ShadeFlag)) {
   12760            0 :                     auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12761            0 :                     auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
   12762            0 :                     auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
   12763            0 :                     Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12764              :                     // Calc diffuse solar absorbed by blind [W]
   12765            0 :                     AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
   12766            0 :                     ShBlDifSolarAbsW = SolarTrans_ViewFactor * AbsDiffBkBl;
   12767              :                 }
   12768              :                 // Correct for divider shadowing
   12769            0 :                 if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
   12770            0 :                     ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
   12771              :                 }
   12772              : 
   12773              :                 // Accumulate diffuse solar absorbed  by shade or screen [W/m2] for heat balance calcs
   12774            0 :                 s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += (ShBlDifSolarAbsW / surf.Area);
   12775              : 
   12776              :                 // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12777              :                 // below
   12778            0 :                 DifSolarAbsW += ShBlDifSolarAbsW;
   12779              : 
   12780              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12781              :                 //                    WinDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
   12782              :                 //                    ZoneDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
   12783              : 
   12784              :                 // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12785              :                 // conservation of energy This is not very effective since it assigns whatever distributed diffuse
   12786              :                 // solar has not been absorbed or reflected to transmitted.
   12787            0 :                 DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
   12788              :                 //                    WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12789              :                 //                    ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12790              : 
   12791              :                 // Accumulate transmitted diffuse solar for reporting
   12792            0 :                 state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
   12793              : 
   12794              :             } // End of shading flag check
   12795              : 
   12796              :             // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
   12797              :             // I would need revised view factors that included these surface types.
   12798              :             // By ignoring them here, the diffuse solar is accounted for on the other surfaces
   12799              : 
   12800              :             //          IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN  ! Window has a frame
   12801              :             // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
   12802              :             //          END IF
   12803              : 
   12804              :             //          IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN  ! Window has dividers
   12805              :             //            DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
   12806              :             //            IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended divider;
   12807              :             //            account for inside glass
   12808              :             //              MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
   12809              :             //              TransGl = dataMaterial.Material(MatNumGl)%Trans
   12810              :             //              ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
   12811              :             //              AbsGl = 1.0d0-TransGl-ReflGl
   12812              :             //              DividerSolRefl = 1.0d0-DividerSolAbs
   12813              :             //              DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
   12814              :             //              DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
   12815              :             //            END IF
   12816              :             // Correct for interior shade transmittance
   12817              :             //            IF(ShadeFlag == IntShadeOn) THEN
   12818              :             //              MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
   12819              :             //              DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
   12820              :             //            ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
   12821              :             //              DividerSolAbs = DividerSolAbs *
   12822              :             //              InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
   12823              :             //                  SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
   12824              :             //            END IF
   12825              :             // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
   12826              : 
   12827              :             //          END IF  ! Window has dividers
   12828              :         } // opaque or window heat transfer surface
   12829              : 
   12830              :     } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
   12831            0 :     state.dataHeatBal->EnclSolInitialDifSolReflW(IntWinEnclosureNum) += InitialZoneDifSolReflW_zone;
   12832              : 
   12833              :     // Check debug var for view factors here
   12834              :     // ViewFactorTotal
   12835              :     // Check debug vars for individual transmitting surfaces here
   12836              :     //        WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
   12837              :     //        WinDifSolarDistTransmittedTotl; //Debug
   12838              :     // WinDifSolarTrans
   12839            0 : }
   12840              : 
   12841            0 : void CalcComplexWindowOverlap(EnergyPlusData &state,
   12842              :                               BSDFGeomDescr &Geom,               // State Geometry
   12843              :                               BSDFWindowGeomDescr const &Window, // Window Geometry
   12844              :                               int const ISurf                    // Surface number of the complex fenestration
   12845              : )
   12846              : {
   12847              :     // SUBROUTINE INFORMATION:
   12848              :     //       AUTHOR         Simon Vidanovic
   12849              :     //       DATE WRITTEN   May 2012
   12850              :     //       MODIFIED       Simon Vidanovic (May 2013) - added overlaps calculations for daylighting
   12851              :     //       RE-ENGINEERED  na
   12852              : 
   12853              :     // PURPOSE OF THIS SUBROUTINE:
   12854              :     // For each of basis directions on back surface of the window calculates
   12855              :     // overlap areas. It also calculates overlap areas and reflectances for daylighting calculations
   12856              : 
   12857              :     using namespace Vectors;
   12858              : 
   12859              :     Real64 XShadowProjection; // temporary buffer
   12860              :     Real64 YShadowProjection; // temporary buffer
   12861              : 
   12862              :     Real64 XSp;            // for calc BSDF projection direction
   12863              :     Real64 YSp;            // for calc BSDF projection direction
   12864              :     Real64 ZSp;            // for calc BSDF projection direction
   12865              :     Real64 SdotX;          // temporary variable for manipulating .dot. product
   12866              :     Real64 SdotY;          // temporary variable for manipulating .dot. product
   12867              :     Real64 SdotZ;          // temporary variable for manipulating .dot. product
   12868              :     int BackSurfaceNumber; // current back surface number
   12869              :     int NVT;               // Number of vertices of back surface
   12870              :     int NS1;               // Number of the figure being overlapped
   12871              :     int NS2;               // Number of the figure doing overlapping
   12872              :     int NS3;               // Location to place results of overlap
   12873              :     int IRay;              // Current ray of BSDF direction
   12874              :     int KBkSurf;           // Current back surface
   12875              :     int N;
   12876              : 
   12877              :     // Daylighting
   12878              :     int IConst;                // Construction number of back surface
   12879              :     int InsideConLay;          // Construction's inside material layer number
   12880              :     Real64 VisibleReflectance; // Visible reflectance for inside surface material
   12881              :     Real64 TotAOverlap;        // Total overlap area for given outgoing direction
   12882              :     Real64 TotARhoVisOverlap;  // Total overlap area time reflectance for given outgoing direction
   12883              : 
   12884            0 :     auto &s_surf = state.dataSurface;
   12885              : 
   12886            0 :     state.dataSolarShading->XVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
   12887            0 :     state.dataSolarShading->YVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
   12888            0 :     state.dataSolarShading->ZVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
   12889              : 
   12890            0 :     Geom.AOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
   12891            0 :     Geom.ARhoVisOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
   12892            0 :     Geom.AveRhoVisOverlap.dimension(Geom.Trn.NBasis, 0.0);
   12893              : 
   12894              :     // First to calculate and store coordinates of the window surface
   12895            0 :     state.dataSolarShading->LOCHCA = 1;
   12896            0 :     int BaseSurf = s_surf->Surface(ISurf).BaseSurf; // Base surface number
   12897              : 
   12898              :     // Base surface contains current window surface (ISurf).
   12899              :     // Since that is case, below transformation should always return ZVT = 0.0
   12900              :     // for every possible transformation
   12901            0 :     CTRANS(state, ISurf, BaseSurf, NVT, state.dataSolarShading->XVertex, state.dataSolarShading->YVertex, state.dataSolarShading->ZVertex);
   12902              : 
   12903              :     // HTRANS routine is using coordinates stored in XVS and YVS in order to calculate
   12904              :     // surface area.  Since both projections are equal to zero, then simply
   12905              :     // copy these values into XVS and YVS arrays
   12906            0 :     for (N = 1; N <= NVT; ++N) {
   12907            0 :         state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N);
   12908            0 :         state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N);
   12909              :     }
   12910              : 
   12911              :     // This calculates the area stored in XVS and YVS
   12912            0 :     HTRANS1(state, state.dataSolarShading->LOCHCA, NVT);
   12913              : 
   12914              :     // Calculation of overlap areas for each outgoing basis direction
   12915            0 :     for (IRay = 1; IRay <= Geom.Trn.NBasis; ++IRay) { // basis directions loop (on back surface)
   12916              :         // For current basis direction calculate dot product between window surface
   12917              :         // and basis direction.  This will be used to calculate projection of each
   12918              :         // of the back surfaces to window surface for given basis direction
   12919            0 :         SdotX = dot(s_surf->Surface(ISurf).lcsx, Geom.sTrn(IRay));
   12920            0 :         SdotY = dot(s_surf->Surface(ISurf).lcsy, Geom.sTrn(IRay));
   12921            0 :         SdotZ = dot(s_surf->Surface(ISurf).lcsz, Geom.sTrn(IRay));
   12922            0 :         XSp = -SdotX;
   12923            0 :         YSp = -SdotY;
   12924            0 :         ZSp = -SdotZ;
   12925              : 
   12926              :         // Projection of shadows for current basis direction
   12927            0 :         if (std::abs(ZSp) > Constant::SmallDistance) {
   12928            0 :             XShadowProjection = XSp / ZSp;
   12929            0 :             YShadowProjection = YSp / ZSp;
   12930            0 :             if (std::abs(XShadowProjection) < 1.e-8) {
   12931            0 :                 XShadowProjection = 0.0;
   12932              :             }
   12933            0 :             if (std::abs(YShadowProjection) < 1.e-8) {
   12934            0 :                 YShadowProjection = 0.0;
   12935              :             }
   12936              :         } else {
   12937            0 :             XShadowProjection = 0.0;
   12938            0 :             YShadowProjection = 0.0;
   12939              :         }
   12940              : 
   12941            0 :         for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
   12942              :             // BaseSurf = Surface(ISurf).BaseSurf
   12943            0 :             BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
   12944              : 
   12945              :             // Transform coordinates of back surface from general system to the
   12946              :             // plane of the receiving surface
   12947            0 :             CTRANS(state,
   12948              :                    BackSurfaceNumber,
   12949              :                    BaseSurf,
   12950              :                    NVT,
   12951            0 :                    state.dataSolarShading->XVertex,
   12952            0 :                    state.dataSolarShading->YVertex,
   12953            0 :                    state.dataSolarShading->ZVertex);
   12954              : 
   12955              :             // Project "shadow" from back surface along sun's rays to receiving surface.  Back surface vertices
   12956              :             // become clockwise sequential.
   12957              : 
   12958            0 :             for (N = 1; N <= NVT; ++N) {
   12959            0 :                 state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N) - YShadowProjection * state.dataSolarShading->ZVertex(N);
   12960            0 :                 state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N) - XShadowProjection * state.dataSolarShading->ZVertex(N);
   12961              :             }
   12962              : 
   12963              :             // Transform to the homogeneous coordinate system.
   12964              : 
   12965            0 :             NS3 = state.dataSolarShading->LOCHCA + 1;
   12966            0 :             state.dataSolarShading->HCT(NS3) = 0.0;
   12967            0 :             HTRANS1(state, NS3, NVT);
   12968              : 
   12969              :             // Determine area of overlap of projected back surface and receiving surface.
   12970              : 
   12971            0 :             NS1 = 1;
   12972            0 :             NS2 = NS3;
   12973            0 :             state.dataSolarShading->HCT(NS3) = 1.0;
   12974            0 :             DeterminePolygonOverlap(state, NS1, NS2, NS3);
   12975              : 
   12976            0 :             if (state.dataSolarShading->OverlapStatus == NoOverlap) {
   12977            0 :                 continue; // to next back surface
   12978              :             }
   12979            0 :             if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
   12980            0 :                 break; // back surfaces DO loop
   12981              :             }
   12982              : 
   12983            0 :             state.dataSolarShading->LOCHCA = NS3;
   12984            0 :             state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
   12985            0 :             state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
   12986              : 
   12987            0 :             Geom.AOverlap(KBkSurf, IRay) = state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
   12988              :         } // DO KBkSurf  = 1 , NBkSurf
   12989              : 
   12990              :         // If some of back surfaces is contained in base surface, then need to subtract shadow of subsurface
   12991              :         // from shadow on base surface.  Reason is that above shadowing algorithm is calculating shadow without
   12992              :         // influence of subsurfaces
   12993            0 :         for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
   12994            0 :             BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
   12995              :             // CurBaseSurf is Current base surface number for shadow overlap calculations
   12996            0 :             int CurBaseSurf = s_surf->Surface(BackSurfaceNumber).BaseSurf;
   12997            0 :             if (CurBaseSurf != BackSurfaceNumber) {
   12998              :                 // Search if that base surface in list of back surfaces for current window
   12999              :                 // CurBackSurface is Current back surface number for base surface
   13000            0 :                 int CurBackSurface = 0;
   13001            0 :                 for (N = 1; N <= Window.NBkSurf; ++N) {
   13002            0 :                     if (state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(N) == CurBaseSurf) {
   13003            0 :                         CurBackSurface = N;
   13004            0 :                         break;
   13005              :                     }
   13006              :                 }
   13007            0 :                 if (CurBackSurface != 0) {
   13008            0 :                     Geom.AOverlap(CurBackSurface, IRay) -= Geom.AOverlap(KBkSurf, IRay);
   13009              :                 }
   13010              :             }
   13011              :         }
   13012              : 
   13013            0 :         auto &s_mat = state.dataMaterial;
   13014              : 
   13015              :         // Calculate overlap area times reflectance.  This is necessary for complex fenestration daylighting
   13016              :         // calculations
   13017            0 :         TotAOverlap = 0.0;
   13018            0 :         TotARhoVisOverlap = 0.0;
   13019            0 :         for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
   13020            0 :             BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
   13021            0 :             IConst = s_surf->Surface(BackSurfaceNumber).Construction;
   13022            0 :             InsideConLay = state.dataConstruction->Construct(IConst).TotLayers;
   13023            0 :             if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
   13024            0 :                 VisibleReflectance = state.dataConstruction->Construct(IConst).ReflectVisDiffBack;
   13025              :             } else {
   13026            0 :                 VisibleReflectance = (1.0 - s_mat->materials(InsideConLay)->AbsorpVisible);
   13027              :             }
   13028            0 :             Geom.ARhoVisOverlap(KBkSurf, IRay) = Geom.AOverlap(KBkSurf, IRay) * VisibleReflectance;
   13029            0 :             TotAOverlap += Geom.AOverlap(KBkSurf, IRay);
   13030            0 :             TotARhoVisOverlap += Geom.ARhoVisOverlap(KBkSurf, IRay);
   13031              :         }
   13032              : 
   13033            0 :         if (TotAOverlap != 0.0) {
   13034            0 :             Geom.AveRhoVisOverlap(IRay) = TotARhoVisOverlap / TotAOverlap;
   13035              :         }
   13036              : 
   13037              :     } // DO IRay = 1, Geom%Trn%NBasis
   13038              : 
   13039              :     // Reset back shadowing counter since complex windows do not need it anymore
   13040            0 :     state.dataSolarShading->LOCHCA = 1;
   13041            0 : }
   13042              : 
   13043       249956 : void TimestepInitComplexFenestration(EnergyPlusData &state)
   13044              : {
   13045              :     // SUBROUTINE INFORMATION:
   13046              :     //       AUTHOR         Simon Vidanovic
   13047              :     //       DATE WRITTEN   May 2012
   13048              :     //       MODIFIED       May 2012 (Initialize complex fenestration in case of EMS)
   13049              :     //       RE-ENGINEERED  na
   13050              : 
   13051              :     // PURPOSE OF THIS SUBROUTINE:
   13052              :     // Performs initialization of complex fenestration. It also performs check if current surface containing
   13053              :     // complex fenestration have construction changed (by EMS) in which case performs addition of current states
   13054              :     // into complex fenestration array
   13055              : 
   13056              :     using WindowComplexManager::CheckCFSStates;
   13057              : 
   13058              :     // Locals
   13059              :     int iSurf;       // Current surface number
   13060              :     int iState;      // current state number
   13061              :     int NumOfStates; // number of states for current window
   13062              : 
   13063       249956 :     auto &s_surf = state.dataSurface;
   13064              : 
   13065      2353940 :     for (iSurf = 1; iSurf <= s_surf->TotSurfaces; ++iSurf) {
   13066      2103984 :         if (s_surf->SurfWinWindowModelType(iSurf) == WindowModel::BSDF) {
   13067              :             // This will check complex fenestrations state and add new one if necessary (EMS case)
   13068            0 :             CheckCFSStates(state, iSurf);
   13069              : 
   13070            0 :             NumOfStates = state.dataBSDFWindow->ComplexWind(iSurf).NumStates;
   13071              : 
   13072              :             // Check for overlap areas and initialize if necessary
   13073            0 :             for (iState = 1; iState <= NumOfStates; ++iState) {
   13074              :                 // do initialization only once
   13075            0 :                 if (state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState) {
   13076            0 :                     CalcComplexWindowOverlap(
   13077            0 :                         state, state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState), state.dataBSDFWindow->ComplexWind(iSurf), iSurf);
   13078            0 :                     state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState = false;
   13079              :                 }
   13080              :             }
   13081              :         }
   13082              :     }
   13083       249956 : }
   13084              : 
   13085              : } // namespace EnergyPlus::SolarShading
        

Generated by: LCOV version 2.0-1