LCOV - code coverage report
Current view: top level - EnergyPlus - SurfaceGeometry.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 5730 9016 63.6 %
Date: 2023-01-17 19:17:23 Functions: 92 99 92.9 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, 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 <string>
      53             : 
      54             : // ObjexxFCL Headers
      55             : #include <ObjexxFCL/Fmath.hh>
      56             : #include <ObjexxFCL/member.functions.hh>
      57             : #include <ObjexxFCL/string.functions.hh>
      58             : 
      59             : // EnergyPlus Headers
      60             : #include <EnergyPlus/Construction.hh>
      61             : #include <EnergyPlus/ConvectionCoefficients.hh>
      62             : #include <EnergyPlus/ConvectionConstants.hh>
      63             : #include <EnergyPlus/Data/EnergyPlusData.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/DataLoopNode.hh>
      70             : #include <EnergyPlus/DataReportingFlags.hh>
      71             : #include <EnergyPlus/DataViewFactorInformation.hh>
      72             : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
      73             : #include <EnergyPlus/DataZoneEquipment.hh>
      74             : #include <EnergyPlus/DaylightingManager.hh>
      75             : #include <EnergyPlus/DisplayRoutines.hh>
      76             : #include <EnergyPlus/EMSManager.hh>
      77             : #include <EnergyPlus/General.hh>
      78             : #include <EnergyPlus/GlobalNames.hh>
      79             : #include <EnergyPlus/HeatBalanceManager.hh>
      80             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      81             : #include <EnergyPlus/Material.hh>
      82             : #include <EnergyPlus/NodeInputManager.hh>
      83             : #include <EnergyPlus/OutAirNodeManager.hh>
      84             : #include <EnergyPlus/OutputProcessor.hh>
      85             : #include <EnergyPlus/OutputReportPredefined.hh>
      86             : #include <EnergyPlus/ScheduleManager.hh>
      87             : #include <EnergyPlus/SolarShading.hh>
      88             : #include <EnergyPlus/SurfaceGeometry.hh>
      89             : #include <EnergyPlus/UtilityRoutines.hh>
      90             : #include <EnergyPlus/Vectors.hh>
      91             : #include <EnergyPlus/WeatherManager.hh>
      92             : #include <EnergyPlus/WindowManager.hh>
      93             : 
      94             : namespace EnergyPlus {
      95             : 
      96             : namespace SurfaceGeometry {
      97             : 
      98             :     // Module containing the routines dealing with the Surface Geometry
      99             : 
     100             :     // MODULE INFORMATION:
     101             :     //       AUTHOR         Linda Lawrie
     102             :     //       DATE WRITTEN   June 2000
     103             :     //       MODIFIED       DJS (PSU Dec 2006) to add ecoroof
     104             :     //       RE-ENGINEERED  na
     105             : 
     106             :     // PURPOSE OF THIS MODULE:
     107             :     // This module performs the functions required of the surface geometry.
     108             : 
     109             :     using namespace DataEnvironment;
     110             :     using namespace DataHeatBalance;
     111             :     using namespace DataSurfaces;
     112             :     using DataWindowEquivalentLayer::CFSMAXNL;
     113             : 
     114         771 :     static std::string const BlankString;
     115             : 
     116             :     int constexpr UnenteredAdjacentZoneSurface = -998; // allows users to enter one zone surface ("Zone")
     117             :                                                        // referencing another in adjacent zone
     118             :     int constexpr UnreconciledZoneSurface = -999;      // interim value between entering surfaces ("Surface") and reconciling
     119             : 
     120         771 :     void AllocateSurfaceWindows(EnergyPlusData &state, int NumSurfaces)
     121             :     {
     122         771 :         state.dataSurface->SurfWinA.dimension(state.dataSurface->TotSurfaces, CFSMAXNL + 1, 0.0);
     123         771 :         state.dataSurface->SurfWinADiffFront.dimension(state.dataSurface->TotSurfaces, CFSMAXNL + 1, 0.0);
     124         771 :         state.dataSurface->SurfWinACFOverlap.dimension(state.dataSurface->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
     125             : 
     126         771 :         state.dataSurface->SurfWinFrameQRadOutAbs.dimension(NumSurfaces, 0);
     127         771 :         state.dataSurface->SurfWinFrameQRadInAbs.dimension(NumSurfaces, 0);
     128         771 :         state.dataSurface->SurfWinDividerQRadOutAbs.dimension(NumSurfaces, 0);
     129         771 :         state.dataSurface->SurfWinDividerQRadInAbs.dimension(NumSurfaces, 0);
     130         771 :         state.dataSurface->SurfWinExtBeamAbsByShade.dimension(NumSurfaces, 0);
     131         771 :         state.dataSurface->SurfWinExtDiffAbsByShade.dimension(NumSurfaces, 0);
     132         771 :         state.dataSurface->SurfWinIntBeamAbsByShade.dimension(NumSurfaces, 0);
     133         771 :         state.dataSurface->SurfWinIntSWAbsByShade.dimension(NumSurfaces, 0);
     134         771 :         state.dataSurface->SurfWinInitialDifSolAbsByShade.dimension(NumSurfaces, 0);
     135         771 :         state.dataSurface->SurfWinIntLWAbsByShade.dimension(NumSurfaces, 0);
     136         771 :         state.dataSurface->SurfWinConvHeatFlowNatural.dimension(NumSurfaces, 0);
     137         771 :         state.dataSurface->SurfWinConvHeatGainToZoneAir.dimension(NumSurfaces, 0);
     138         771 :         state.dataSurface->SurfWinRetHeatGainToZoneAir.dimension(NumSurfaces, 0);
     139         771 :         state.dataSurface->SurfWinDividerHeatGain.dimension(NumSurfaces, 0);
     140         771 :         state.dataSurface->SurfWinBlTsolBmBm.dimension(NumSurfaces, 0);
     141         771 :         state.dataSurface->SurfWinBlTsolBmDif.dimension(NumSurfaces, 0);
     142         771 :         state.dataSurface->SurfWinBlTsolDifDif.dimension(NumSurfaces, 0);
     143         771 :         state.dataSurface->SurfWinBlGlSysTsolBmBm.dimension(NumSurfaces, 0);
     144         771 :         state.dataSurface->SurfWinBlGlSysTsolDifDif.dimension(NumSurfaces, 0);
     145         771 :         state.dataSurface->SurfWinScTsolBmBm.dimension(NumSurfaces, 0);
     146         771 :         state.dataSurface->SurfWinScTsolBmDif.dimension(NumSurfaces, 0);
     147         771 :         state.dataSurface->SurfWinScTsolDifDif.dimension(NumSurfaces, 0);
     148         771 :         state.dataSurface->SurfWinScGlSysTsolBmBm.dimension(NumSurfaces, 0);
     149         771 :         state.dataSurface->SurfWinScGlSysTsolDifDif.dimension(NumSurfaces, 0);
     150         771 :         state.dataSurface->SurfWinGlTsolBmBm.dimension(NumSurfaces, 0);
     151         771 :         state.dataSurface->SurfWinGlTsolBmDif.dimension(NumSurfaces, 0);
     152         771 :         state.dataSurface->SurfWinGlTsolDifDif.dimension(NumSurfaces, 0);
     153         771 :         state.dataSurface->SurfWinBmSolTransThruIntWinRep.dimension(NumSurfaces, 0);
     154         771 :         state.dataSurface->SurfWinBmSolAbsdOutsReveal.dimension(NumSurfaces, 0);
     155         771 :         state.dataSurface->SurfWinBmSolRefldOutsRevealReport.dimension(NumSurfaces, 0);
     156         771 :         state.dataSurface->SurfWinBmSolAbsdInsReveal.dimension(NumSurfaces, 0);
     157         771 :         state.dataSurface->SurfWinBmSolRefldInsReveal.dimension(NumSurfaces, 0);
     158         771 :         state.dataSurface->SurfWinBmSolRefldInsRevealReport.dimension(NumSurfaces, 0);
     159         771 :         state.dataSurface->SurfWinOutsRevealDiffOntoGlazing.dimension(NumSurfaces, 0);
     160         771 :         state.dataSurface->SurfWinInsRevealDiffOntoGlazing.dimension(NumSurfaces, 0);
     161         771 :         state.dataSurface->SurfWinInsRevealDiffIntoZone.dimension(NumSurfaces, 0);
     162         771 :         state.dataSurface->SurfWinOutsRevealDiffOntoFrame.dimension(NumSurfaces, 0);
     163         771 :         state.dataSurface->SurfWinInsRevealDiffOntoFrame.dimension(NumSurfaces, 0);
     164         771 :         state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport.dimension(NumSurfaces, 0);
     165         771 :         state.dataSurface->SurfWinInsRevealDiffIntoZoneReport.dimension(NumSurfaces, 0);
     166         771 :         state.dataSurface->SurfWinInsRevealDiffOntoFrameReport.dimension(NumSurfaces, 0);
     167         771 :         state.dataSurface->SurfWinBmSolAbsdInsRevealReport.dimension(NumSurfaces, 0);
     168         771 :         state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy.dimension(NumSurfaces, 0);
     169         771 :         state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy.dimension(NumSurfaces, 0);
     170         771 :         state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy.dimension(NumSurfaces, 0);
     171         771 :         state.dataSurface->SurfWinProfileAngHor.dimension(NumSurfaces, 0);
     172         771 :         state.dataSurface->SurfWinProfileAngVert.dimension(NumSurfaces, 0);
     173             : 
     174         771 :         state.dataSurface->SurfWinShadingFlag.dimension(NumSurfaces, WinShadingType::ShadeOff);
     175         771 :         state.dataSurface->SurfWinShadingFlagEMSOn.dimension(NumSurfaces, 0);
     176         771 :         state.dataSurface->SurfWinShadingFlagEMSValue.dimension(NumSurfaces, 0.0);
     177         771 :         state.dataSurface->SurfWinStormWinFlag.dimension(NumSurfaces, 0);
     178         771 :         state.dataSurface->SurfWinStormWinFlagPrevDay.dimension(NumSurfaces, 0);
     179         771 :         state.dataSurface->SurfWinFracTimeShadingDeviceOn.dimension(NumSurfaces, 0);
     180         771 :         state.dataSurface->SurfWinExtIntShadePrevTS.dimension(NumSurfaces, WinShadingType::ShadeOff);
     181         771 :         state.dataSurface->SurfWinHasShadeOrBlindLayer.dimension(NumSurfaces, 0);
     182         771 :         state.dataSurface->SurfWinSurfDayLightInit.dimension(NumSurfaces, 0);
     183         771 :         state.dataSurface->SurfWinDaylFacPoint.dimension(NumSurfaces, 0);
     184         771 :         state.dataSurface->SurfWinVisTransSelected.dimension(NumSurfaces, 0);
     185         771 :         state.dataSurface->SurfWinSwitchingFactor.dimension(NumSurfaces, 0);
     186         771 :         state.dataSurface->SurfWinTheta.dimension(NumSurfaces, 0);
     187         771 :         state.dataSurface->SurfWinPhi.dimension(NumSurfaces, 0);
     188         771 :         state.dataSurface->SurfWinRhoCeilingWall.dimension(NumSurfaces, 0);
     189         771 :         state.dataSurface->SurfWinRhoFloorWall.dimension(NumSurfaces, 0);
     190         771 :         state.dataSurface->SurfWinFractionUpgoing.dimension(NumSurfaces, 0);
     191         771 :         state.dataSurface->SurfWinVisTransRatio.dimension(NumSurfaces, 0);
     192         771 :         state.dataSurface->SurfWinIRfromParentZone.dimension(NumSurfaces, 0);
     193         771 :         state.dataSurface->SurfWinFrameArea.dimension(NumSurfaces, 0);
     194         771 :         state.dataSurface->SurfWinFrameConductance.dimension(NumSurfaces, 0);
     195         771 :         state.dataSurface->SurfWinFrameSolAbsorp.dimension(NumSurfaces, 0);
     196         771 :         state.dataSurface->SurfWinFrameVisAbsorp.dimension(NumSurfaces, 0);
     197         771 :         state.dataSurface->SurfWinFrameEmis.dimension(NumSurfaces, 0);
     198         771 :         state.dataSurface->SurfWinFrEdgeToCenterGlCondRatio.dimension(NumSurfaces, 1.0);
     199         771 :         state.dataSurface->SurfWinFrameEdgeArea.dimension(NumSurfaces, 0);
     200         771 :         state.dataSurface->SurfWinFrameTempIn.dimension(NumSurfaces, 23.0);
     201         771 :         state.dataSurface->SurfWinFrameTempInOld.dimension(NumSurfaces, 23.0);
     202         771 :         state.dataSurface->SurfWinFrameTempSurfOut.dimension(NumSurfaces, 23.0);
     203         771 :         state.dataSurface->SurfWinProjCorrFrOut.dimension(NumSurfaces, 0);
     204         771 :         state.dataSurface->SurfWinProjCorrFrIn.dimension(NumSurfaces, 0);
     205         771 :         state.dataSurface->SurfWinDividerType.dimension(NumSurfaces, DataSurfaces::FrameDividerType::DividedLite);
     206         771 :         state.dataSurface->SurfWinDividerArea.dimension(NumSurfaces, 0);
     207         771 :         state.dataSurface->SurfWinDividerConductance.dimension(NumSurfaces, 0);
     208         771 :         state.dataSurface->SurfWinDividerSolAbsorp.dimension(NumSurfaces, 0);
     209         771 :         state.dataSurface->SurfWinDividerVisAbsorp.dimension(NumSurfaces, 0);
     210         771 :         state.dataSurface->SurfWinDividerEmis.dimension(NumSurfaces, 0);
     211         771 :         state.dataSurface->SurfWinDivEdgeToCenterGlCondRatio.dimension(NumSurfaces, 1);
     212         771 :         state.dataSurface->SurfWinDividerEdgeArea.dimension(NumSurfaces, 0);
     213         771 :         state.dataSurface->SurfWinDividerTempIn.dimension(NumSurfaces, 23.0);
     214         771 :         state.dataSurface->SurfWinDividerTempInOld.dimension(NumSurfaces, 23.0);
     215         771 :         state.dataSurface->SurfWinDividerTempSurfOut.dimension(NumSurfaces, 23.0);
     216         771 :         state.dataSurface->SurfWinProjCorrDivOut.dimension(NumSurfaces, 0);
     217         771 :         state.dataSurface->SurfWinProjCorrDivIn.dimension(NumSurfaces, 0);
     218         771 :         state.dataSurface->SurfWinGlazedFrac.dimension(NumSurfaces, 1);
     219         771 :         state.dataSurface->SurfWinCenterGlArea.dimension(NumSurfaces, 0);
     220         771 :         state.dataSurface->SurfWinEdgeGlCorrFac.dimension(NumSurfaces, 1);
     221         771 :         state.dataSurface->SurfWinOriginalClass.dimension(NumSurfaces, SurfaceClass::None);
     222         771 :         state.dataSurface->SurfWinShadeAbsFacFace1.dimension(NumSurfaces, 0.5);
     223         771 :         state.dataSurface->SurfWinShadeAbsFacFace2.dimension(NumSurfaces, 0.5);
     224         771 :         state.dataSurface->SurfWinConvCoeffWithShade.dimension(NumSurfaces, 0);
     225         771 :         state.dataSurface->SurfWinOtherConvHeatGain.dimension(NumSurfaces, 0);
     226         771 :         state.dataSurface->SurfWinBlindNumber.dimension(NumSurfaces, 0);
     227         771 :         state.dataSurface->SurfWinEffInsSurfTemp.dimension(NumSurfaces, 23.0);
     228         771 :         state.dataSurface->SurfWinMovableSlats.dimension(NumSurfaces, 0);
     229         771 :         state.dataSurface->SurfWinSlatAngThisTS.dimension(NumSurfaces, 0);
     230         771 :         state.dataSurface->SurfWinSlatAngThisTSDeg.dimension(NumSurfaces, 0);
     231         771 :         state.dataSurface->SurfWinSlatAngThisTSDegEMSon.dimension(NumSurfaces, 0);
     232         771 :         state.dataSurface->SurfWinSlatAngThisTSDegEMSValue.dimension(NumSurfaces, 0);
     233         771 :         state.dataSurface->SurfWinSlatsBlockBeam.dimension(NumSurfaces, 0);
     234         771 :         state.dataSurface->SurfWinSlatsAngIndex.dimension(NumSurfaces, 0);
     235         771 :         state.dataSurface->SurfWinSlatsAngInterpFac.dimension(NumSurfaces, 0);
     236         771 :         state.dataSurface->SurfWinProfileAng.dimension(NumSurfaces, 0);
     237         771 :         state.dataSurface->SurfWinProfAngIndex.dimension(NumSurfaces, 0);
     238         771 :         state.dataSurface->SurfWinProfAngInterpFac.dimension(NumSurfaces, 0);
     239         771 :         state.dataSurface->SurfWinBlindBmBmTrans.dimension(NumSurfaces, 0);
     240         771 :         state.dataSurface->SurfWinBlindAirFlowPermeability.dimension(NumSurfaces, 0);
     241         771 :         state.dataSurface->SurfWinTotGlazingThickness.dimension(NumSurfaces, 0);
     242         771 :         state.dataSurface->SurfWinTanProfileAngHor.dimension(NumSurfaces, 0);
     243         771 :         state.dataSurface->SurfWinTanProfileAngVert.dimension(NumSurfaces, 0);
     244         771 :         state.dataSurface->SurfWinInsideSillDepth.dimension(NumSurfaces, 0);
     245         771 :         state.dataSurface->SurfWinInsideReveal.dimension(NumSurfaces, 0);
     246         771 :         state.dataSurface->SurfWinInsideSillSolAbs.dimension(NumSurfaces, 0);
     247         771 :         state.dataSurface->SurfWinInsideRevealSolAbs.dimension(NumSurfaces, 0);
     248         771 :         state.dataSurface->SurfWinOutsideRevealSolAbs.dimension(NumSurfaces, 0);
     249         771 :         state.dataSurface->SurfWinScreenNumber.dimension(NumSurfaces, 0);
     250         771 :         state.dataSurface->SurfWinAirflowSource.dimension(NumSurfaces, DataSurfaces::WindowAirFlowSource::Invalid);
     251         771 :         state.dataSurface->SurfWinAirflowDestination.dimension(NumSurfaces, DataSurfaces::WindowAirFlowDestination::Invalid);
     252         771 :         state.dataSurface->SurfWinAirflowReturnNodePtr.dimension(NumSurfaces, 0);
     253         771 :         state.dataSurface->SurfWinMaxAirflow.dimension(NumSurfaces, 0);
     254         771 :         state.dataSurface->SurfWinAirflowControlType.dimension(NumSurfaces, DataSurfaces::WindowAirFlowControlType::Invalid);
     255         771 :         state.dataSurface->SurfWinAirflowHasSchedule.dimension(NumSurfaces, 0);
     256         771 :         state.dataSurface->SurfWinAirflowSchedulePtr.dimension(NumSurfaces, 0);
     257         771 :         state.dataSurface->SurfWinAirflowThisTS.dimension(NumSurfaces, 0);
     258         771 :         state.dataSurface->SurfWinTAirflowGapOutlet.dimension(NumSurfaces, 0);
     259         771 :         state.dataSurface->SurfWinWindowCalcIterationsRep.dimension(NumSurfaces, 0);
     260         771 :         state.dataSurface->SurfWinVentingOpenFactorMultRep.dimension(NumSurfaces, 0);
     261         771 :         state.dataSurface->SurfWinInsideTempForVentingRep.dimension(NumSurfaces, 0);
     262         771 :         state.dataSurface->SurfWinVentingAvailabilityRep.dimension(NumSurfaces, 0);
     263         771 :         state.dataSurface->SurfWinSkyGndSolarInc.dimension(NumSurfaces, 0);
     264         771 :         state.dataSurface->SurfWinBmGndSolarInc.dimension(NumSurfaces, 0);
     265         771 :         state.dataSurface->SurfWinLightWellEff.dimension(NumSurfaces, 1);
     266         771 :         state.dataSurface->SurfWinSolarDiffusing.dimension(NumSurfaces, 0);
     267         771 :         state.dataSurface->SurfWinFrameHeatGain.dimension(NumSurfaces, 0);
     268         771 :         state.dataSurface->SurfWinFrameHeatLoss.dimension(NumSurfaces, 0);
     269         771 :         state.dataSurface->SurfWinDividerHeatLoss.dimension(NumSurfaces, 0);
     270         771 :         state.dataSurface->SurfWinTCLayerTemp.dimension(NumSurfaces, 0);
     271         771 :         state.dataSurface->SurfWinSpecTemp.dimension(NumSurfaces, 0);
     272         771 :         state.dataSurface->SurfWinWindowModelType.dimension(NumSurfaces, WindowModel::Detailed);
     273         771 :         state.dataSurface->SurfWinTDDPipeNum.dimension(NumSurfaces, 0);
     274         771 :         state.dataSurface->SurfWinStormWinConstr.dimension(NumSurfaces, 0);
     275         771 :         state.dataSurface->SurfActiveConstruction.dimension(NumSurfaces, 0);
     276         771 :         state.dataSurface->SurfWinActiveShadedConstruction.dimension(NumSurfaces, 0);
     277         771 :     }
     278             : 
     279         771 :     void SetupZoneGeometry(EnergyPlusData &state, bool &ErrorsFound)
     280             :     {
     281             : 
     282             :         // SUBROUTINE INFORMATION:
     283             :         //       AUTHOR         George Walton
     284             :         //       DATE WRITTEN   September 1977
     285             :         //       MODIFIED       April 2002 (FCW): add warning for Solar Distribution
     286             :         //                      = FullInteriorExterior when window has reveal
     287             :         //                      Add fatal error when triangular window has reveal
     288             :         //                      May 2002(FCW): Allow triangular windows to have reveal (subr SHDRVL
     289             :         //                      in SolarShading). Remove above warning and fatal error.
     290             :         //       RE-ENGINEERED  November 1997 (RKS,LKL)
     291             : 
     292             :         // PURPOSE OF THIS SUBROUTINE:
     293             :         // This subroutine controls the processing of detached shadowing and
     294             :         // zone surfaces for computing their vertices.
     295             : 
     296             :         using namespace DataVectorTypes;
     297             :         using namespace OutputReportPredefined;
     298             : 
     299             :         static constexpr std::string_view RoutineName("SetUpZoneGeometry: ");
     300             : 
     301             :         Real64 AverageHeight; // Used to keep track of average height of a surface/zone
     302             :         Real64 ZMax;          // Maximum Z of a surface (detailed outside coefficient calculation)
     303             :         Real64 ZMin;          // Minimum Z of a surface (detailed outside coefficient calculation)
     304             :         Real64 ZCeilAvg;
     305             :         Real64 CeilCount;
     306             :         Real64 ZFlrAvg;
     307             :         Real64 FloorCount;
     308             :         Real64 TotSurfArea;
     309             :         Real64 Z1;
     310             :         Real64 Z2;
     311        1542 :         std::string String1;
     312        1542 :         std::string String2;
     313        1542 :         std::string String3;
     314             :         int Count; // To count wall surfaces for ceiling height calculation
     315        1542 :         Array1D_bool ZoneCeilingHeightEntered;
     316        1542 :         Array1D<Real64> ZoneCeilingArea;
     317         771 :         auto &ErrCount = state.dataSurfaceGeometry->ErrCount;
     318             :         Real64 NominalUwithConvCoeffs;
     319        1542 :         std::string cNominalU;
     320        1542 :         std::string cNominalUwithConvCoeffs;
     321             :         bool isWithConvCoefValid;
     322             :         bool nonInternalMassSurfacesPresent;
     323             :         bool DetailedWWR;
     324             : 
     325             :         // Zones must have been "gotten" before this call
     326             :         // The RelNorth variables are used if "relative" coordinates are input as well
     327             :         // as setting up DaylightingCoords
     328             : 
     329             :         // these include building north axis and Building Rotation for Appendix G
     330         771 :         state.dataSurfaceGeometry->CosBldgRelNorth =
     331         771 :             std::cos(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * DataGlobalConstants::DegToRadians);
     332         771 :         state.dataSurfaceGeometry->SinBldgRelNorth =
     333         771 :             std::sin(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * DataGlobalConstants::DegToRadians);
     334             : 
     335             :         // these are only for Building Rotation for Appendix G when using world coordinate system
     336         771 :         state.dataSurfaceGeometry->CosBldgRotAppGonly = std::cos(-state.dataHeatBal->BuildingRotationAppendixG * DataGlobalConstants::DegToRadians);
     337         771 :         state.dataSurfaceGeometry->SinBldgRotAppGonly = std::sin(-state.dataHeatBal->BuildingRotationAppendixG * DataGlobalConstants::DegToRadians);
     338             : 
     339         771 :         state.dataSurfaceGeometry->CosZoneRelNorth.allocate(state.dataGlobal->NumOfZones);
     340         771 :         state.dataSurfaceGeometry->SinZoneRelNorth.allocate(state.dataGlobal->NumOfZones);
     341             : 
     342         771 :         ZoneCeilingHeightEntered.dimension(state.dataGlobal->NumOfZones, false);
     343         771 :         ZoneCeilingArea.dimension(state.dataGlobal->NumOfZones, 0.0);
     344             : 
     345        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     346             : 
     347        4814 :             state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) =
     348        4814 :                 std::cos(-state.dataHeatBal->Zone(ZoneNum).RelNorth * DataGlobalConstants::DegToRadians);
     349        4814 :             state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) =
     350        4814 :                 std::sin(-state.dataHeatBal->Zone(ZoneNum).RelNorth * DataGlobalConstants::DegToRadians);
     351             :         }
     352         771 :         GetSurfaceData(state, ErrorsFound);
     353             : 
     354         771 :         if (ErrorsFound) {
     355           0 :             state.dataSurfaceGeometry->CosZoneRelNorth.deallocate();
     356           0 :             state.dataSurfaceGeometry->SinZoneRelNorth.deallocate();
     357           0 :             return;
     358             :         }
     359             : 
     360         771 :         GetWindowGapAirflowControlData(state, ErrorsFound);
     361             : 
     362         771 :         GetStormWindowData(state, ErrorsFound);
     363             : 
     364         771 :         if (!ErrorsFound && state.dataSurface->TotStormWin > 0) CreateStormWindowConstructions(state);
     365             : 
     366         771 :         SetFlagForWindowConstructionWithShadeOrBlindLayer(state);
     367             : 
     368         771 :         state.dataSurfaceGeometry->CosZoneRelNorth.deallocate();
     369         771 :         state.dataSurfaceGeometry->SinZoneRelNorth.deallocate();
     370             : 
     371         771 :         state.dataHeatBal->CalcWindowRevealReflection = false; // Set to True in ProcessSurfaceVertices if beam solar reflection from window reveals
     372             :         // is requested for one or more exterior windows.
     373         771 :         state.dataSurface->BuildingShadingCount = 0;
     374         771 :         state.dataSurface->FixedShadingCount = 0;
     375         771 :         state.dataSurface->AttachedShadingCount = 0;
     376         771 :         state.dataSurface->ShadingSurfaceFirst = -1;
     377         771 :         state.dataSurface->ShadingSurfaceLast = -1;
     378             : 
     379             :         // Reserve space to avoid excess allocations
     380         771 :         state.dataSurface->AllExtSolAndShadingSurfaceList.reserve(state.dataSurface->TotSurfaces);
     381             : 
     382       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { // Loop through all surfaces...
     383       43762 :             auto &thisSurface = state.dataSurface->Surface(SurfNum);
     384             : 
     385       43762 :             state.dataSurface->SurfAirSkyRadSplit(SurfNum) = std::sqrt(0.5 * (1.0 + thisSurface.CosTilt));
     386             : 
     387             :             // Set flag that determines whether a surface is a shadowing surface
     388       43762 :             thisSurface.IsShadowing = false;
     389       86022 :             if (thisSurface.Class == SurfaceClass::Shading || thisSurface.Class == SurfaceClass::Detached_F ||
     390       42260 :                 thisSurface.Class == SurfaceClass::Detached_B) {
     391        1542 :                 thisSurface.IsShadowing = true;
     392        1542 :                 if (state.dataSurface->ShadingSurfaceFirst == -1) state.dataSurface->ShadingSurfaceFirst = SurfNum;
     393        1542 :                 state.dataSurface->ShadingSurfaceLast = SurfNum;
     394             :             }
     395       43762 :             if ((thisSurface.HeatTransSurf && thisSurface.ExtSolar) || thisSurface.IsShadowing) {
     396             :                 // Some attached shading surfaces may be true for both
     397       18505 :                 state.dataSurface->AllExtSolAndShadingSurfaceList.push_back(SurfNum);
     398             :             }
     399       43762 :             if (thisSurface.Class == SurfaceClass::Shading) ++state.dataSurface->AttachedShadingCount;
     400       43762 :             if (thisSurface.Class == SurfaceClass::Detached_F) ++state.dataSurface->FixedShadingCount;
     401       43762 :             if (thisSurface.Class == SurfaceClass::Detached_B) ++state.dataSurface->BuildingShadingCount;
     402             : 
     403       43762 :             if (thisSurface.Class != SurfaceClass::IntMass) ProcessSurfaceVertices(state, SurfNum, ErrorsFound);
     404             :         }
     405             : 
     406        5585 :         for (auto &e : state.dataHeatBal->Zone) {
     407        4814 :             e.ExtWindowArea = 0.0;
     408        4814 :             e.HasWindow = false;
     409        4814 :             e.ExtGrossWallArea = 0.0;
     410        4814 :             e.ExtNetWallArea = 0.0;
     411        4814 :             e.TotalSurfArea = 0.0;
     412             :         }
     413             : 
     414        5594 :         for (auto &s : state.dataHeatBal->space) {
     415        4823 :             s.extWindowArea = 0.0;
     416        4823 :             s.totalSurfArea = 0.0;
     417             :         }
     418         771 :         DetailedWWR = (state.dataInputProcessing->inputProcessor->getNumSectionsFound("DETAILEDWWR_DEBUG") > 0);
     419         771 :         if (DetailedWWR) {
     420           0 :             print(state.files.debug, "{}", "=======User Entered Classification =================");
     421           0 :             print(state.files.debug, "{}", "Surface,Class,Area,Tilt");
     422             :         }
     423             : 
     424       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { // Loop through all surfaces to find windows...
     425       43762 :             auto &thisSurface = state.dataSurface->Surface(SurfNum);
     426             : 
     427       43762 :             if (!thisSurface.HeatTransSurf && !thisSurface.IsAirBoundarySurf) continue; // Skip shadowing (sub)surfaces
     428       42220 :             auto &thisZone = state.dataHeatBal->Zone(thisSurface.Zone);
     429       42220 :             auto &thisSpace = state.dataHeatBal->space(thisSurface.spaceNum);
     430             : 
     431       42220 :             thisZone.TotalSurfArea += thisSurface.Area;
     432       42220 :             thisSpace.totalSurfArea += thisSurface.Area;
     433       42220 :             if (state.dataConstruction->Construct(thisSurface.Construction).TypeIsWindow) {
     434        5976 :                 thisZone.TotalSurfArea += state.dataSurface->SurfWinFrameArea(SurfNum);
     435        5976 :                 thisZone.HasWindow = true;
     436        5976 :                 thisSpace.totalSurfArea += state.dataSurface->SurfWinFrameArea(SurfNum);
     437             :             }
     438       42220 :             if (thisSurface.Class == SurfaceClass::Roof) ZoneCeilingArea(thisSurface.Zone) += thisSurface.GrossArea;
     439       42220 :             if (!state.dataConstruction->Construct(thisSurface.Construction).TypeIsWindow) {
     440       36244 :                 if (thisSurface.ExtBoundCond == ExternalEnvironment || thisSurface.ExtBoundCond == OtherSideCondModeledExt) {
     441       11159 :                     thisZone.ExteriorTotalSurfArea += thisSurface.GrossArea;
     442       11159 :                     thisSpace.ExteriorTotalSurfArea += thisSurface.GrossArea;
     443       22318 :                     if (thisSurface.Class == SurfaceClass::Wall) {
     444        8488 :                         thisZone.ExtNetWallArea += thisSurface.Area;
     445        8488 :                         thisZone.ExtGrossWallArea += thisSurface.GrossArea;
     446        8488 :                         thisSpace.ExtGrossWallArea += thisSurface.GrossArea;
     447        8488 :                         thisZone.ExtGrossWallArea_Multiplied += thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier;
     448        8488 :                         if (DetailedWWR) {
     449           0 :                             print(state.files.debug,
     450             :                                   "{},Wall,{:.2R},{:.1R}\n",
     451             :                                   thisSurface.Name,
     452           0 :                                   thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier,
     453           0 :                                   thisSurface.Tilt);
     454             :                         }
     455             :                     }
     456       47874 :                 } else if (thisSurface.ExtBoundCond == Ground || thisSurface.ExtBoundCond == GroundFCfactorMethod ||
     457       22789 :                            thisSurface.ExtBoundCond == KivaFoundation) {
     458        2334 :                     thisZone.ExteriorTotalGroundSurfArea += thisSurface.GrossArea;
     459        2334 :                     if (thisSurface.Class == SurfaceClass::Wall) {
     460         195 :                         thisZone.ExtGrossGroundWallArea += thisSurface.GrossArea;
     461         195 :                         thisZone.ExtGrossGroundWallArea_Multiplied += thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier;
     462         195 :                         if (DetailedWWR) {
     463           0 :                             print(state.files.debug,
     464             :                                   "{},Wall-GroundContact,{:.2R},{:.1R}\n",
     465             :                                   thisSurface.Name,
     466           0 :                                   thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier,
     467           0 :                                   thisSurface.Tilt);
     468             :                         }
     469             :                     }
     470             :                 }
     471             : 
     472             :             } else { // For Windows
     473             : 
     474       11938 :                 if (((thisSurface.ExtBoundCond == ExternalEnvironment) || (thisSurface.ExtBoundCond == OtherSideCondModeledExt)) &&
     475        5962 :                     (thisSurface.Class != SurfaceClass::TDD_Dome)) {
     476        5960 :                     thisZone.ExtWindowArea += thisSurface.GrossArea;
     477        5960 :                     thisSpace.extWindowArea += thisSurface.GrossArea;
     478        5960 :                     thisZone.ExtWindowArea_Multiplied =
     479        5960 :                         thisZone.ExtWindowArea + thisSurface.GrossArea * thisSurface.Multiplier * thisZone.Multiplier * thisZone.ListMultiplier;
     480        5960 :                     if (DetailedWWR) {
     481           0 :                         print(state.files.debug,
     482             :                               "{},Window,{:.2R},{:.1R}\n",
     483             :                               thisSurface.Name,
     484           0 :                               thisSurface.GrossArea * thisSurface.Multiplier * thisZone.Multiplier * thisZone.ListMultiplier,
     485           0 :                               thisSurface.Tilt);
     486             :                     }
     487             :                 }
     488             :             }
     489             : 
     490             :         } // ...end of surfaces windows DO loop
     491             : 
     492         771 :         if (DetailedWWR) {
     493           0 :             print(state.files.debug, "{}\n", "========================");
     494           0 :             print(state.files.debug, "{}\n", "Zone,ExtWallArea,ExtWindowArea");
     495             :         }
     496             : 
     497        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     498        4814 :             auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
     499        9632 :             for (int spaceNum : thisZone.spaceIndexes) {
     500        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     501        4818 :                 CeilCount = 0.0;
     502        4818 :                 FloorCount = 0.0;
     503        4818 :                 Count = 0;
     504        4818 :                 AverageHeight = 0.0;
     505        4818 :                 ZCeilAvg = 0.0;
     506        4818 :                 ZFlrAvg = 0.0;
     507        4818 :                 ZMax = -99999.0;
     508        4818 :                 ZMin = 99999.0;
     509        4818 :                 if (DetailedWWR) {
     510           0 :                     print(state.files.debug, "{},{:.2R},{:.2R}\n", thisZone.Name, thisZone.ExtGrossWallArea, thisZone.ExtWindowArea);
     511             :                 }
     512             :                 // Use AllSurfaceFirst which includes air boundaries
     513       47038 :                 for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
     514       42220 :                     auto &thisSurface = state.dataSurface->Surface(SurfNum);
     515             : 
     516       42220 :                     if (thisSurface.Class == SurfaceClass::Roof) {
     517             :                         // Use Average Z for surface, more important for roofs than floors...
     518        5490 :                         ++CeilCount;
     519        5490 :                         Z1 = minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
     520        5490 :                         Z2 = maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
     521             :                         //        ZCeilAvg=ZCeilAvg+(Z1+Z2)/2.d0
     522        5490 :                         ZCeilAvg += ((Z1 + Z2) / 2.0) * (thisSurface.GrossArea / ZoneCeilingArea(ZoneNum));
     523             :                     }
     524       42220 :                     if (thisSurface.Class == SurfaceClass::Floor) {
     525             :                         // Use Average Z for surface, more important for roofs than floors...
     526        6522 :                         ++FloorCount;
     527        6522 :                         Z1 = minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
     528        6522 :                         Z2 = maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
     529             :                         //        ZFlrAvg=ZFlrAvg+(Z1+Z2)/2.d0
     530        6522 :                         ZFlrAvg += ((Z1 + Z2) / 2.0) * (thisSurface.Area / thisZone.FloorArea);
     531             :                     }
     532       42220 :                     if (thisSurface.Class == SurfaceClass::Wall) {
     533             :                         // Use Wall calculation in case no roof & floor in zone
     534       21482 :                         ++Count;
     535       21482 :                         if (Count == 1) {
     536        4794 :                             ZMax = thisSurface.Vertex(1).z;
     537        4794 :                             ZMin = ZMax;
     538             :                         }
     539       21482 :                         ZMax = max(ZMax, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
     540       21482 :                         ZMin = min(ZMin, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
     541             :                     }
     542             :                 }
     543        4818 :                 if (CeilCount > 0.0 && FloorCount > 0.0) {
     544        4812 :                     AverageHeight = ZCeilAvg - ZFlrAvg;
     545             :                 } else {
     546           6 :                     AverageHeight = (ZMax - ZMin);
     547             :                 }
     548        4818 :                 if (AverageHeight <= 0.0) {
     549           2 :                     AverageHeight = (ZMax - ZMin);
     550             :                 }
     551             : 
     552        4818 :                 if (thisZone.CeilingHeight > 0.0) {
     553        1754 :                     ZoneCeilingHeightEntered(ZoneNum) = true;
     554        1754 :                     if (AverageHeight > 0.0) {
     555        1752 :                         if (std::abs(AverageHeight - thisZone.CeilingHeight) / thisZone.CeilingHeight > 0.05) {
     556          11 :                             if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
     557           0 :                                 ShowWarningError(
     558             :                                     state,
     559           0 :                                     std::string{RoutineName} +
     560             :                                         "Entered Ceiling Height for some zone(s) significantly different from calculated Ceiling Height");
     561           0 :                                 ShowContinueError(
     562             :                                     state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on each max iteration exceeded.");
     563             :                             }
     564          11 :                             if (state.dataGlobal->DisplayExtraWarnings) {
     565           0 :                                 ShowWarningError(state,
     566           0 :                                                  std::string{RoutineName} + "Entered Ceiling Height for Zone=\"" + thisZone.Name +
     567             :                                                      "\" significantly different from calculated Ceiling Height");
     568             :                                 static constexpr std::string_view ValFmt("{:.2F}");
     569           0 :                                 String1 = format(ValFmt, thisZone.CeilingHeight);
     570           0 :                                 String2 = format(ValFmt, AverageHeight);
     571           0 :                                 ShowContinueError(state,
     572           0 :                                                   std::string{RoutineName} + "Entered Ceiling Height=" + String1 +
     573           0 :                                                       ", Calculated Ceiling Height=" + String2 + ", entered height will be used in calculations.");
     574             :                             }
     575             :                         }
     576             :                     }
     577             :                 }
     578        4818 :                 if ((thisZone.CeilingHeight <= 0.0) && (AverageHeight > 0.0)) thisZone.CeilingHeight = AverageHeight;
     579             :                 // Need to add check here - don't touch if already user-specified
     580             :             }
     581             :         }
     582             : 
     583         771 :         CalculateZoneVolume(state, ZoneCeilingHeightEntered); // Calculate Zone Volumes
     584             : 
     585             :         // Calculate zone centroid (and min/max x,y,z for zone)
     586             :         // Use AllSurfaceFirst which includes air boundaries
     587        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     588        4814 :             auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
     589        4814 :             nonInternalMassSurfacesPresent = false;
     590        4814 :             TotSurfArea = 0.0;
     591        4814 :             thisZone.Centroid = Vector(0.0, 0.0, 0.0);
     592        4814 :             if (state.dataSurface->Surface(thisZone.AllSurfaceFirst).Sides > 0) {
     593        4814 :                 thisZone.MinimumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
     594        4814 :                 thisZone.MaximumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
     595        4814 :                 thisZone.MinimumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
     596        4814 :                 thisZone.MaximumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
     597        4814 :                 thisZone.MinimumZ = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).z;
     598        4814 :                 thisZone.MaximumZ = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).z;
     599             :             }
     600        9632 :             for (int spaceNum : thisZone.spaceIndexes) {
     601        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     602             : 
     603       47038 :                 for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
     604       42220 :                     auto &thisSurface = state.dataSurface->Surface(SurfNum);
     605       42220 :                     if (thisSurface.Class == SurfaceClass::IntMass) continue;
     606       39936 :                     nonInternalMassSurfacesPresent = true;
     607       52900 :                     if (thisSurface.Class == SurfaceClass::Wall || (thisSurface.Class == SurfaceClass::Roof) ||
     608       12964 :                         (thisSurface.Class == SurfaceClass::Floor)) {
     609             : 
     610       33494 :                         thisZone.Centroid.x += thisSurface.Centroid.x * thisSurface.GrossArea;
     611       33494 :                         thisZone.Centroid.y += thisSurface.Centroid.y * thisSurface.GrossArea;
     612       33494 :                         thisZone.Centroid.z += thisSurface.Centroid.z * thisSurface.GrossArea;
     613       33494 :                         TotSurfArea += thisSurface.GrossArea;
     614             :                     }
     615       39936 :                     thisZone.MinimumX = min(thisZone.MinimumX, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::x));
     616       39936 :                     thisZone.MaximumX = max(thisZone.MaximumX, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::x));
     617       39936 :                     thisZone.MinimumY = min(thisZone.MinimumY, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::y));
     618       39936 :                     thisZone.MaximumY = max(thisZone.MaximumY, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::y));
     619       39936 :                     thisZone.MinimumZ = min(thisZone.MinimumZ, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
     620       39936 :                     thisZone.MaximumZ = max(thisZone.MaximumZ, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
     621             :                 }
     622             :             }
     623        4814 :             if (TotSurfArea > 0.0) {
     624        4814 :                 thisZone.Centroid.x /= TotSurfArea;
     625        4814 :                 thisZone.Centroid.y /= TotSurfArea;
     626        4814 :                 thisZone.Centroid.z /= TotSurfArea;
     627             :             }
     628        4814 :             if (!nonInternalMassSurfacesPresent) {
     629           0 :                 ShowSevereError(state,
     630           0 :                                 std::string{RoutineName} + "Zone=\"" + thisZone.Name +
     631             :                                     "\" has only internal mass surfaces.  Need at least one other surface.");
     632           0 :                 ErrorsFound = true;
     633             :             }
     634             :         }
     635             : 
     636         771 :         ZoneCeilingHeightEntered.deallocate();
     637         771 :         ZoneCeilingArea.deallocate();
     638             : 
     639         771 :         state.dataSurface->SurfAdjacentZone.dimension(state.dataSurface->TotSurfaces, 0);
     640             :         // note -- adiabatic surfaces will show same zone as surface
     641       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     642       43762 :             if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue;
     643       22732 :             state.dataSurface->SurfAdjacentZone(SurfNum) = state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).ExtBoundCond).Zone;
     644             :         }
     645             : 
     646        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     647     1205695 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     648     1200881 :                 auto &thisSurface = state.dataSurface->Surface(SurfNum);
     649     1200881 :                 if (!thisSurface.HeatTransSurf && thisSurface.ZoneName == state.dataHeatBal->Zone(ZoneNum).Name)
     650        1416 :                     ++state.dataHeatBal->Zone(ZoneNum).NumShadingSurfaces;
     651             : 
     652     1200881 :                 if (thisSurface.Zone != ZoneNum) continue;
     653             : 
     654       84426 :                 if (thisSurface.HeatTransSurf &&
     655       62944 :                     (thisSurface.Class == SurfaceClass::Wall || thisSurface.Class == SurfaceClass::Roof || thisSurface.Class == SurfaceClass::Floor))
     656       33480 :                     ++state.dataHeatBal->Zone(ZoneNum).NumSurfaces;
     657             : 
     658       78452 :                 if (thisSurface.HeatTransSurf && (thisSurface.Class == SurfaceClass::Window || thisSurface.Class == SurfaceClass::GlassDoor ||
     659      107762 :                                                   thisSurface.Class == SurfaceClass::Door || thisSurface.Class == SurfaceClass::TDD_Dome ||
     660       35764 :                                                   thisSurface.Class == SurfaceClass::TDD_Diffuser))
     661        6442 :                     ++state.dataHeatBal->Zone(ZoneNum).NumSubSurfaces;
     662             : 
     663             :             } // surfaces
     664             :         }     // zones
     665             : 
     666       44533 :         for (int const SurfNum : state.dataSurface->AllSurfaceListReportOrder) {
     667       43762 :             auto &thisSurface = state.dataSurface->Surface(SurfNum);
     668       43762 :             if (thisSurface.Construction > 0 && thisSurface.Construction <= state.dataHeatBal->TotConstructs) {
     669       42220 :                 NominalUwithConvCoeffs = ComputeNominalUwithConvCoeffs(state, SurfNum, isWithConvCoefValid);
     670       42220 :                 if (isWithConvCoefValid) {
     671       42206 :                     cNominalUwithConvCoeffs = format("{:.3R}", NominalUwithConvCoeffs);
     672             :                 } else {
     673          14 :                     cNominalUwithConvCoeffs = "[invalid]";
     674             :                 }
     675       42220 :                 if ((thisSurface.Class == SurfaceClass::Window) || (thisSurface.Class == SurfaceClass::TDD_Dome)) {
     676             :                     // SurfaceClass::Window also covers glass doors and TDD:Diffusers
     677        5976 :                     cNominalU = "N/A";
     678             :                 } else {
     679       36244 :                     cNominalU = format("{:.3R}", state.dataHeatBal->NominalU(thisSurface.Construction));
     680             :                 }
     681             :             } else {
     682        1542 :                 cNominalUwithConvCoeffs = "**";
     683        1542 :                 cNominalU = "**";
     684             :             }
     685             : 
     686             :             // populate the predefined report related to u-values with films
     687             :             // only exterior surfaces including underground
     688       43762 :             auto const SurfaceClass(thisSurface.Class);
     689       66786 :             if ((thisSurface.ExtBoundCond == ExternalEnvironment) || (thisSurface.ExtBoundCond == Ground) ||
     690       46010 :                 (thisSurface.ExtBoundCond == KivaFoundation) || (thisSurface.ExtBoundCond == GroundFCfactorMethod)) {
     691       41910 :                 if ((SurfaceClass == SurfaceClass::Wall) || (SurfaceClass == SurfaceClass::Floor) || (SurfaceClass == SurfaceClass::Roof)) {
     692       13065 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchOpUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     693        7890 :                 } else if (SurfaceClass == SurfaceClass::Door) {
     694         386 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchDrUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     695             :                 }
     696             :             } else {
     697       22807 :                 if ((SurfaceClass == SurfaceClass::Wall) || (SurfaceClass == SurfaceClass::Floor) || (SurfaceClass == SurfaceClass::Roof)) {
     698       20429 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntOpUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     699        2378 :                 } else if (SurfaceClass == SurfaceClass::Door) {
     700          80 :                     PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntDrUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     701             :                 }
     702             :             }
     703             :         } // surfaces
     704             : 
     705             :         // Write number of shadings to initialization output file
     706         771 :         print(state.files.eio,
     707         771 :               "! <Shading Summary>, Number of Fixed Detached Shades, Number of Building Detached Shades, Number of Attached Shades\n");
     708             : 
     709        3084 :         print(state.files.eio,
     710             :               " Shading Summary,{},{},{}\n",
     711         771 :               state.dataSurface->FixedShadingCount,
     712         771 :               state.dataSurface->BuildingShadingCount,
     713        1542 :               state.dataSurface->AttachedShadingCount);
     714             : 
     715             :         // Write number of zones header to initialization output file
     716         771 :         print(state.files.eio, "! <Zone Summary>, Number of Zones, Number of Zone Surfaces, Number of SubSurfaces\n");
     717             : 
     718        1542 :         print(state.files.eio,
     719             :               " Zone Summary,{},{},{}\n",
     720         771 :               state.dataGlobal->NumOfZones,
     721        2313 :               state.dataSurface->TotSurfaces - state.dataSurface->FixedShadingCount - state.dataSurface->BuildingShadingCount -
     722         771 :                   state.dataSurface->AttachedShadingCount,
     723        2313 :               sum(state.dataHeatBal->Zone, &ZoneData::NumSubSurfaces));
     724             : 
     725             :         // Write Zone Information header to the initialization output file
     726             :         static constexpr std::string_view Format_721(
     727             :             "! <Zone Information>,Zone Name,North Axis {deg},Origin X-Coordinate {m},Origin Y-Coordinate {m},Origin Z-Coordinate "
     728             :             "{m},Centroid X-Coordinate {m},Centroid Y-Coordinate {m},Centroid Z-Coordinate {m},Type,Zone Multiplier,Zone List "
     729             :             "Multiplier,Minimum X {m},Maximum X {m},Minimum Y {m},Maximum Y {m},Minimum Z {m},Maximum Z {m},Ceiling Height {m},Volume "
     730             :             "{m3},Zone Inside Convection Algorithm {Simple-Detailed-CeilingDiffuser-TrombeWall},Zone Outside Convection Algorithm "
     731             :             "{Simple-Detailed-Tarp-MoWitt-DOE-2-BLAST}, Floor Area {m2},Exterior Gross Wall Area {m2},Exterior Net Wall Area {m2},Exterior "
     732             :             "Window "
     733             :             "Area {m2}, Number of Surfaces, Number of SubSurfaces, Number of Shading SubSurfaces,  Part of Total Building Area");
     734         771 :         print(state.files.eio, "{}\n", Format_721);
     735             : 
     736        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     737             :             // Write Zone Information to the initialization output file
     738             : 
     739             :             {
     740        4814 :                 auto const SELECT_CASE_var(state.dataHeatBal->Zone(ZoneNum).InsideConvectionAlgo);
     741        4814 :                 if (SELECT_CASE_var == ConvectionConstants::HcInt_ASHRAESimple) {
     742        1055 :                     String1 = "Simple";
     743        3759 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcInt_ASHRAETARP) {
     744        3733 :                     String1 = "TARP";
     745          26 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcInt_CeilingDiffuser) {
     746          10 :                     String1 = "CeilingDiffuser";
     747          16 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcInt_TrombeWall) {
     748           1 :                     String1 = "TrombeWall";
     749          15 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcInt_AdaptiveConvectionAlgorithm) {
     750          14 :                     String1 = "AdaptiveConvectionAlgorithm";
     751           1 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcInt_ASTMC1340) {
     752           1 :                     String1 = "ASTMC1340";
     753             :                 }
     754             :             }
     755             : 
     756             :             {
     757        4814 :                 auto const SELECT_CASE_var(state.dataHeatBal->Zone(ZoneNum).OutsideConvectionAlgo);
     758        4814 :                 if (SELECT_CASE_var == ConvectionConstants::HcExt_ASHRAESimple) {
     759        1063 :                     String2 = "Simple";
     760        3751 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcExt_ASHRAETARP) {
     761         492 :                     String2 = "TARP";
     762        3259 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcExt_TarpHcOutside) {
     763           0 :                     String2 = "TARP";
     764        3259 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcExt_MoWiTTHcOutside) {
     765           0 :                     String2 = "MoWitt";
     766        3259 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcExt_DOE2HcOutside) {
     767        3243 :                     String2 = "DOE-2";
     768          16 :                 } else if (SELECT_CASE_var == ConvectionConstants::HcExt_AdaptiveConvectionAlgorithm) {
     769          16 :                     String2 = "AdaptiveConvectionAlgorithm";
     770             :                 }
     771             :             }
     772             : 
     773        4814 :             if (state.dataHeatBal->Zone(ZoneNum).isPartOfTotalArea) {
     774        4679 :                 String3 = "Yes";
     775             :             } else {
     776         135 :                 String3 = "No";
     777             :             }
     778             : 
     779             :             static constexpr std::string_view Format_720(
     780             :                 " Zone Information, "
     781             :                 "{},{:.1R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{},{},{},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},"
     782             :                 "{:.2R},{:.2R},{},{},{:.2R},{:.2R},{:.2R},{:.2R},{},{},{},{}\n");
     783             : 
     784      125164 :             print(state.files.eio,
     785             :                   Format_720,
     786        4814 :                   state.dataHeatBal->Zone(ZoneNum).Name,
     787        4814 :                   state.dataHeatBal->Zone(ZoneNum).RelNorth,
     788        4814 :                   state.dataHeatBal->Zone(ZoneNum).OriginX,
     789        4814 :                   state.dataHeatBal->Zone(ZoneNum).OriginY,
     790        4814 :                   state.dataHeatBal->Zone(ZoneNum).OriginZ,
     791        4814 :                   state.dataHeatBal->Zone(ZoneNum).Centroid.x,
     792        4814 :                   state.dataHeatBal->Zone(ZoneNum).Centroid.y,
     793        4814 :                   state.dataHeatBal->Zone(ZoneNum).Centroid.z,
     794        4814 :                   state.dataHeatBal->Zone(ZoneNum).OfType,
     795        4814 :                   state.dataHeatBal->Zone(ZoneNum).Multiplier,
     796        4814 :                   state.dataHeatBal->Zone(ZoneNum).ListMultiplier,
     797        4814 :                   state.dataHeatBal->Zone(ZoneNum).MinimumX,
     798        4814 :                   state.dataHeatBal->Zone(ZoneNum).MaximumX,
     799        4814 :                   state.dataHeatBal->Zone(ZoneNum).MinimumY,
     800        4814 :                   state.dataHeatBal->Zone(ZoneNum).MaximumY,
     801        4814 :                   state.dataHeatBal->Zone(ZoneNum).MinimumZ,
     802        4814 :                   state.dataHeatBal->Zone(ZoneNum).MaximumZ,
     803        4814 :                   state.dataHeatBal->Zone(ZoneNum).CeilingHeight,
     804        4814 :                   state.dataHeatBal->Zone(ZoneNum).Volume,
     805             :                   String1,
     806             :                   String2,
     807        4814 :                   state.dataHeatBal->Zone(ZoneNum).FloorArea,
     808        4814 :                   state.dataHeatBal->Zone(ZoneNum).ExtGrossWallArea,
     809        4814 :                   state.dataHeatBal->Zone(ZoneNum).ExtNetWallArea,
     810        4814 :                   state.dataHeatBal->Zone(ZoneNum).ExtWindowArea,
     811        4814 :                   state.dataHeatBal->Zone(ZoneNum).NumSurfaces,
     812        4814 :                   state.dataHeatBal->Zone(ZoneNum).NumSubSurfaces,
     813        4814 :                   state.dataHeatBal->Zone(ZoneNum).NumShadingSurfaces,
     814             :                   String3);
     815             : 
     816             :         } // ZoneNum
     817             : 
     818             :         // Set up solar distribution enclosures allowing for any air boundaries
     819         771 :         SetupEnclosuresAndAirBoundaries(state, state.dataViewFactor->EnclSolInfo, SurfaceGeometry::enclosureType::SolarEnclosures, ErrorsFound);
     820             : 
     821             :         // Do the Stratosphere check
     822         771 :         SetZoneOutBulbTempAt(state);
     823         771 :         CheckZoneOutBulbTempAt(state);
     824             :     }
     825             : 
     826         771 :     void AllocateSurfaceArrays(EnergyPlusData &state)
     827             :     {
     828             : 
     829             :         // SUBROUTINE INFORMATION:
     830             :         //       AUTHOR         Rick Strand
     831             :         //       DATE WRITTEN   February 1998
     832             :         //       MODIFIED       na
     833             :         //       RE-ENGINEERED  na
     834             : 
     835             :         // PURPOSE OF THIS SUBROUTINE:
     836             :         // This subroutine allocates all of the arrays at the module level which
     837             :         // require allocation.
     838             : 
     839             :         // METHODOLOGY EMPLOYED:
     840             :         // Allocation is dependent on the user input file.
     841             : 
     842             :         // REFERENCES:
     843             :         // na
     844             : 
     845             :         // USE STATEMENTS:
     846             :         // na
     847             : 
     848             :         // SUBROUTINE PARAMETER DEFINITIONS:
     849             :         // na
     850             : 
     851             :         // INTERFACE BLOCK SPECIFICATIONS
     852             :         // na
     853             : 
     854             :         // DERIVED TYPE DEFINITIONS
     855             :         // na
     856             : 
     857             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     858             :         // na
     859         771 :         state.dataSurface->ShadeV.allocate(state.dataSurface->TotSurfaces);
     860       44533 :         for (auto &e : state.dataSurface->ShadeV)
     861       43762 :             e.NVert = 0;
     862             :         // Individual components (XV,YV,ZV) allocated in routine ProcessSurfaceVertices
     863         771 :         state.dataSurface->X0.dimension(state.dataSurface->TotSurfaces, 0.0);
     864         771 :         state.dataSurface->Y0.dimension(state.dataSurface->TotSurfaces, 0.0);
     865         771 :         state.dataSurface->Z0.dimension(state.dataSurface->TotSurfaces, 0.0);
     866             : 
     867             :         // Surface EMS arrays
     868         771 :         state.dataSurface->SurfEMSConstructionOverrideON.allocate(state.dataSurface->TotSurfaces);
     869         771 :         state.dataSurface->SurfEMSConstructionOverrideValue.allocate(state.dataSurface->TotSurfaces);
     870         771 :         state.dataSurface->SurfEMSOverrideIntConvCoef.allocate(state.dataSurface->TotSurfaces);
     871         771 :         state.dataSurface->SurfEMSValueForIntConvCoef.allocate(state.dataSurface->TotSurfaces);
     872         771 :         state.dataSurface->SurfEMSOverrideExtConvCoef.allocate(state.dataSurface->TotSurfaces);
     873         771 :         state.dataSurface->SurfEMSValueForExtConvCoef.allocate(state.dataSurface->TotSurfaces);
     874         771 :         state.dataSurface->SurfOutDryBulbTempEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     875         771 :         state.dataSurface->SurfOutDryBulbTempEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     876         771 :         state.dataSurface->SurfOutWetBulbTempEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     877         771 :         state.dataSurface->SurfOutWetBulbTempEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     878         771 :         state.dataSurface->SurfWindSpeedEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     879         771 :         state.dataSurface->SurfWindSpeedEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     880         771 :         state.dataSurface->SurfViewFactorGroundEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     881         771 :         state.dataSurface->SurfViewFactorGroundEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     882         771 :         state.dataSurface->SurfWindDirEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     883         771 :         state.dataSurface->SurfWindDirEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     884       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     885       43762 :             state.dataSurface->SurfEMSConstructionOverrideON(SurfNum) = false;
     886       43762 :             state.dataSurface->SurfEMSConstructionOverrideValue(SurfNum) = 0.0;
     887       43762 :             state.dataSurface->SurfEMSOverrideIntConvCoef(SurfNum) = false;
     888       43762 :             state.dataSurface->SurfEMSValueForIntConvCoef(SurfNum) = 0.0;
     889       43762 :             state.dataSurface->SurfEMSOverrideExtConvCoef(SurfNum) = false;
     890       43762 :             state.dataSurface->SurfEMSValueForExtConvCoef(SurfNum) = 0.0;
     891       43762 :             state.dataSurface->SurfOutDryBulbTempEMSOverrideOn(SurfNum) = false;
     892       43762 :             state.dataSurface->SurfOutDryBulbTempEMSOverrideValue(SurfNum) = 0.0;
     893       43762 :             state.dataSurface->SurfOutWetBulbTempEMSOverrideOn(SurfNum) = false;
     894       43762 :             state.dataSurface->SurfOutWetBulbTempEMSOverrideValue(SurfNum) = 0.0;
     895       43762 :             state.dataSurface->SurfWindSpeedEMSOverrideOn(SurfNum) = false;
     896       43762 :             state.dataSurface->SurfWindSpeedEMSOverrideValue(SurfNum) = 0.0;
     897       43762 :             state.dataSurface->SurfViewFactorGroundEMSOverrideOn(SurfNum) = false;
     898       43762 :             state.dataSurface->SurfViewFactorGroundEMSOverrideValue(SurfNum) = 0.0;
     899       43762 :             state.dataSurface->SurfWindDirEMSOverrideOn(SurfNum) = false;
     900       43762 :             state.dataSurface->SurfWindDirEMSOverrideValue(SurfNum) = 0.0;
     901             :         }
     902             :         // Following are surface hb arrays
     903         771 :         state.dataSurface->SurfOutDryBulbTemp.allocate(state.dataSurface->TotSurfaces);
     904         771 :         state.dataSurface->SurfOutWetBulbTemp.allocate(state.dataSurface->TotSurfaces);
     905         771 :         state.dataSurface->SurfOutWindSpeed.allocate(state.dataSurface->TotSurfaces);
     906         771 :         state.dataSurface->SurfOutWindDir.allocate(state.dataSurface->TotSurfaces);
     907         771 :         state.dataSurface->SurfGenericContam.allocate(state.dataSurface->TotSurfaces);
     908         771 :         state.dataSurface->SurfPenumbraID.allocate(state.dataSurface->TotSurfaces);
     909         771 :         state.dataSurface->SurfAirSkyRadSplit.allocate(state.dataSurface->TotSurfaces);
     910       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     911       43762 :             state.dataSurface->SurfOutDryBulbTemp(SurfNum) = 0.0;
     912       43762 :             state.dataSurface->SurfOutWetBulbTemp(SurfNum) = 0.0;
     913       43762 :             state.dataSurface->SurfOutWindSpeed(SurfNum) = 0.0;
     914       43762 :             state.dataSurface->SurfOutWindDir(SurfNum) = 0.0;
     915       43762 :             state.dataSurface->SurfGenericContam(SurfNum) = 0.0;
     916       43762 :             state.dataSurface->SurfPenumbraID(SurfNum) = -1;
     917       43762 :             state.dataSurface->SurfAirSkyRadSplit(SurfNum) = 0.0;
     918             :         }
     919             :         // Following are surface property arrays used in SurfaceGeometry
     920         771 :         state.dataSurface->SurfShadowRecSurfNum.allocate(state.dataSurface->TotSurfaces);
     921         771 :         state.dataSurface->SurfShadowDisabledZoneList.allocate(state.dataSurface->TotSurfaces);
     922         771 :         state.dataSurface->SurfShadowDiffuseSolRefl.allocate(state.dataSurface->TotSurfaces);
     923         771 :         state.dataSurface->SurfShadowDiffuseVisRefl.allocate(state.dataSurface->TotSurfaces);
     924         771 :         state.dataSurface->SurfShadowGlazingFrac.allocate(state.dataSurface->TotSurfaces);
     925         771 :         state.dataSurface->SurfShadowGlazingConstruct.allocate(state.dataSurface->TotSurfaces);
     926         771 :         state.dataSurface->SurfMaterialMovInsulExt.allocate(state.dataSurface->TotSurfaces);
     927         771 :         state.dataSurface->SurfMaterialMovInsulInt.allocate(state.dataSurface->TotSurfaces);
     928         771 :         state.dataSurface->SurfSchedMovInsulExt.allocate(state.dataSurface->TotSurfaces);
     929         771 :         state.dataSurface->SurfSchedMovInsulInt.allocate(state.dataSurface->TotSurfaces);
     930       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     931       43762 :             state.dataSurface->SurfShadowRecSurfNum(SurfNum) = 0;
     932       43762 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) = 0.0;
     933       43762 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) = 0.0;
     934       43762 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = 0.0;
     935       43762 :             state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = 0;
     936       43762 :             state.dataSurface->SurfMaterialMovInsulExt(SurfNum) = 0;
     937       43762 :             state.dataSurface->SurfMaterialMovInsulInt(SurfNum) = 0;
     938       43762 :             state.dataSurface->SurfSchedMovInsulExt(SurfNum) = 0;
     939       43762 :             state.dataSurface->SurfSchedMovInsulInt(SurfNum) = 0;
     940             :         }
     941         771 :         state.dataSurface->SurfExtEcoRoof.allocate(state.dataSurface->TotSurfaces);
     942         771 :         state.dataSurface->SurfExtCavityPresent.allocate(state.dataSurface->TotSurfaces);
     943         771 :         state.dataSurface->SurfExtCavNum.allocate(state.dataSurface->TotSurfaces);
     944         771 :         state.dataSurface->SurfIsPV.allocate(state.dataSurface->TotSurfaces);
     945         771 :         state.dataSurface->SurfIsICS.allocate(state.dataSurface->TotSurfaces);
     946         771 :         state.dataSurface->SurfIsPool.allocate(state.dataSurface->TotSurfaces);
     947         771 :         state.dataSurface->SurfICSPtr.allocate(state.dataSurface->TotSurfaces);
     948         771 :         state.dataSurface->SurfIsRadSurfOrVentSlabOrPool.allocate(state.dataSurface->TotSurfaces);
     949         771 :         state.dataSurface->SurfDaylightingShelfInd.allocate(state.dataSurface->TotSurfaces);
     950       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     951       43762 :             state.dataSurface->SurfExtEcoRoof(SurfNum) = false;
     952       43762 :             state.dataSurface->SurfExtCavityPresent(SurfNum) = false;
     953       43762 :             state.dataSurface->SurfExtCavNum(SurfNum) = 0;
     954       43762 :             state.dataSurface->SurfIsPV(SurfNum) = false;
     955       43762 :             state.dataSurface->SurfIsICS(SurfNum) = false;
     956       43762 :             state.dataSurface->SurfIsPool(SurfNum) = false;
     957       43762 :             state.dataSurface->SurfICSPtr(SurfNum) = 0;
     958       43762 :             state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(SurfNum) = false;
     959       43762 :             state.dataSurface->SurfDaylightingShelfInd(SurfNum) = 0;
     960             :         }
     961         771 :         state.dataSurface->SurfLowTempErrCount.allocate(state.dataSurface->TotSurfaces);
     962         771 :         state.dataSurface->SurfHighTempErrCount.allocate(state.dataSurface->TotSurfaces);
     963         771 :         state.dataSurface->SurfIntConvCoeffIndex.allocate(state.dataSurface->TotSurfaces);
     964         771 :         state.dataSurface->SurfExtConvCoeffIndex.allocate(state.dataSurface->TotSurfaces);
     965         771 :         state.dataSurface->SurfTAirRef.allocate(state.dataSurface->TotSurfaces);
     966         771 :         state.dataSurface->SurfTAirRefRpt.allocate(state.dataSurface->TotSurfaces);
     967         771 :         state.dataSurface->SurfIntConvClassification.allocate(state.dataSurface->TotSurfaces);
     968         771 :         state.dataSurface->SurfIntConvClassificationRpt.allocate(state.dataSurface->TotSurfaces);
     969         771 :         state.dataSurface->SurfIntConvHcModelEq.allocate(state.dataSurface->TotSurfaces);
     970         771 :         state.dataSurface->SurfIntConvHcUserCurveIndex.allocate(state.dataSurface->TotSurfaces);
     971         771 :         state.dataSurface->SurfOutConvClassification.allocate(state.dataSurface->TotSurfaces);
     972         771 :         state.dataSurface->SurfOutConvClassificationRpt.allocate(state.dataSurface->TotSurfaces);
     973         771 :         state.dataSurface->SurfOutConvHfModelEq.allocate(state.dataSurface->TotSurfaces);
     974         771 :         state.dataSurface->SurfOutConvHfUserCurveIndex.allocate(state.dataSurface->TotSurfaces);
     975         771 :         state.dataSurface->SurfOutConvHnModelEq.allocate(state.dataSurface->TotSurfaces);
     976         771 :         state.dataSurface->SurfOutConvHnUserCurveIndex.allocate(state.dataSurface->TotSurfaces);
     977         771 :         state.dataSurface->SurfOutConvFaceArea.allocate(state.dataSurface->TotSurfaces);
     978         771 :         state.dataSurface->SurfOutConvFacePerimeter.allocate(state.dataSurface->TotSurfaces);
     979         771 :         state.dataSurface->SurfOutConvFaceHeight.allocate(state.dataSurface->TotSurfaces);
     980         771 :         state.dataSurface->SurfIntConvZoneWallHeight.allocate(state.dataSurface->TotSurfaces);
     981         771 :         state.dataSurface->SurfIntConvZonePerimLength.allocate(state.dataSurface->TotSurfaces);
     982         771 :         state.dataSurface->SurfIntConvZoneHorizHydrDiam.allocate(state.dataSurface->TotSurfaces);
     983         771 :         state.dataSurface->SurfIntConvWindowWallRatio.allocate(state.dataSurface->TotSurfaces);
     984         771 :         state.dataSurface->SurfIntConvWindowLocation.allocate(state.dataSurface->TotSurfaces);
     985         771 :         state.dataSurface->SurfIntConvSurfGetsRadiantHeat.allocate(state.dataSurface->TotSurfaces);
     986         771 :         state.dataSurface->SurfIntConvSurfHasActiveInIt.allocate(state.dataSurface->TotSurfaces);
     987       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     988       43762 :             state.dataSurface->SurfLowTempErrCount(SurfNum) = 0;
     989       43762 :             state.dataSurface->SurfHighTempErrCount(SurfNum) = 0;
     990       43762 :             state.dataSurface->SurfIntConvCoeffIndex(SurfNum) = ConvectionConstants::HcInt_SetByZone;
     991       43762 :             state.dataSurface->SurfExtConvCoeffIndex(SurfNum) = 0;
     992       43762 :             state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::Invalid;
     993       43762 :             state.dataSurface->SurfTAirRefRpt(SurfNum) = static_cast<int>(DataSurfaces::RefAirTemp::Invalid);
     994       43762 :             state.dataSurface->SurfIntConvClassification(SurfNum) = ConvectionConstants::InConvClass::Invalid;
     995       43762 :             state.dataSurface->SurfIntConvClassificationRpt(SurfNum) = static_cast<int>(ConvectionConstants::InConvClass::Invalid);
     996       43762 :             state.dataSurface->SurfIntConvHcModelEq(SurfNum) = 0;
     997       43762 :             state.dataSurface->SurfIntConvHcUserCurveIndex(SurfNum) = 0;
     998       43762 :             state.dataSurface->SurfOutConvClassification(SurfNum) = ConvectionConstants::OutConvClass::Invalid;
     999       43762 :             state.dataSurface->SurfOutConvClassificationRpt(SurfNum) = static_cast<int>(ConvectionConstants::OutConvClass::Invalid);
    1000       43762 :             state.dataSurface->SurfOutConvHfModelEq(SurfNum) = 0;
    1001       43762 :             state.dataSurface->SurfOutConvHfUserCurveIndex(SurfNum) = 0;
    1002       43762 :             state.dataSurface->SurfOutConvHnModelEq(SurfNum) = 0;
    1003       43762 :             state.dataSurface->SurfOutConvHnUserCurveIndex(SurfNum) = 0;
    1004       43762 :             state.dataSurface->SurfOutConvFaceArea(SurfNum) = 0;
    1005       43762 :             state.dataSurface->SurfOutConvFacePerimeter(SurfNum) = 0;
    1006       43762 :             state.dataSurface->SurfOutConvFaceHeight(SurfNum) = 0;
    1007       43762 :             state.dataSurface->SurfIntConvZoneWallHeight(SurfNum) = 0;
    1008       43762 :             state.dataSurface->SurfIntConvZonePerimLength(SurfNum) = 0;
    1009       43762 :             state.dataSurface->SurfIntConvZoneHorizHydrDiam(SurfNum) = 0;
    1010       43762 :             state.dataSurface->SurfIntConvWindowWallRatio(SurfNum) = 0;
    1011       43762 :             state.dataSurface->SurfIntConvWindowLocation(SurfNum) = ConvectionConstants::InConvWinLoc::NotSet;
    1012       43762 :             state.dataSurface->SurfIntConvSurfGetsRadiantHeat(SurfNum) = false;
    1013       43762 :             state.dataSurface->SurfIntConvSurfHasActiveInIt(SurfNum) = false;
    1014             :         }
    1015         771 :     }
    1016             : 
    1017         771 :     void GetSurfaceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    1018             :     {
    1019             : 
    1020             :         // SUBROUTINE INFORMATION:
    1021             :         //       AUTHOR         Richard Liesen
    1022             :         //       DATE WRITTEN   November 1997
    1023             :         //       MODIFIED       April 1999, Linda Lawrie
    1024             :         //                      Dec. 2000, FW (add "one-wall zone" checks)
    1025             :         //       RE-ENGINEERED  May 2000, Linda Lawrie (breakout surface type gets)
    1026             : 
    1027             :         // PURPOSE OF THIS SUBROUTINE:
    1028             :         // The purpose of this subroutine is to read in the surface information
    1029             :         // from the input data file and interpret and put in the derived type
    1030             : 
    1031             :         // METHODOLOGY EMPLOYED:
    1032             :         // The order of surfaces does not matter and the surfaces are resorted into
    1033             :         // the hierarchical order:
    1034             :         //  All Shading Surfaces
    1035             :         //  Airwalls for space x1
    1036             :         //  Base Surfaces for space x1
    1037             :         //  Opaque Subsurfaces for space x1
    1038             :         //  Window Subsurfaces for space x1
    1039             :         //  TDD Dome Surfaces for space x1
    1040             :         //  Airwalls for space x2
    1041             :         //  Base Surfaces for space x2
    1042             :         //  etc
    1043             :         //  Pointers are set in the spaces (AllSurfaceFirst/Last, HTSurfaceFirst/Last, OpaqOrIntMassSurfaceFirst/Last, WindowSurfaceFirst/Last,
    1044             :         //  OpaqOrWinSurfaceFirst/Last, TDDDomeFirst/Last)
    1045             : 
    1046             :         // REFERENCES:
    1047             :         //   This routine manages getting the input for the following Objects:
    1048             :         // SurfaceGeometry
    1049             :         // Surface:Shading:Detached
    1050             :         // Surface:HeatTransfer
    1051             :         // Surface:HeatTransfer:Sub
    1052             :         // Surface:Shading:Attached
    1053             :         // Surface:InternalMass
    1054             : 
    1055             :         // Vertex input:
    1056             :         //  N3 , \field Number of Surface Vertices -- Number of (X,Y,Z) groups in this surface
    1057             :         //       \note currently limited 3 or 4, later?
    1058             :         //       \min 3
    1059             :         //       \max 4
    1060             :         //       \memo vertices are given in SurfaceGeometry coordinates -- if relative, all surface coordinates
    1061             :         //       \memo are "relative" to the Zone Origin.  if WCS, then building and zone origins are used
    1062             :         //       \memo for some internal calculations, but all coordinates are given in an "absolute" system.
    1063             :         //  N4,  \field Vertex 1 X-coordinate
    1064             :         //       \units m
    1065             :         //       \type real
    1066             :         //  N5 , \field Vertex 1 Y-coordinate
    1067             :         //       \units m
    1068             :         //       \type real
    1069             :         //  N6 , \field Vertex 1 Z-coordinate
    1070             :         //       \units m
    1071             :         //       \type real
    1072             :         //  N7,  \field Vertex 2 X-coordinate
    1073             :         //       \units m
    1074             :         //       \type real
    1075             :         //  N8,  \field Vertex 2 Y-coordinate
    1076             :         //       \units m
    1077             :         //       \type real
    1078             :         //  N9,  \field Vertex 2 Z-coordinate
    1079             :         //       \units m
    1080             :         //       \type real
    1081             :         //  N10, \field Vertex 3 X-coordinate
    1082             :         //       \units m
    1083             :         //       \type real
    1084             :         //  N11, \field Vertex 3 Y-coordinate
    1085             :         //       \units m
    1086             :         //       \type real
    1087             :         //  N12, \field Vertex 3 Z-coordinate
    1088             :         //       \units m
    1089             :         //       \type real
    1090             :         //  N13, \field Vertex 4 X-coordinate
    1091             :         //       \units m
    1092             :         //       \type real
    1093             :         //  N14, \field Vertex 4 Y-coordinate
    1094             :         //       \type real
    1095             :         //       \units m
    1096             :         //  N15; \field Vertex 4 Z-coordinate
    1097             :         //       \units m
    1098             :         //       \type real
    1099             : 
    1100             :         // The vertices are stored in the surface derived type.
    1101             :         //      +(1)-------------------------(4)+
    1102             :         //      |                               |
    1103             :         //      |                               |
    1104             :         //      |                               |
    1105             :         //      +(2)-------------------------(3)+
    1106             :         //  The above diagram shows the actual coordinate points of a typical wall
    1107             :         //  (you're on the outside looking toward the wall) as stored into
    1108             :         //  Surface%Vertex(1:<number-of-sides>)
    1109             : 
    1110             :         using namespace Vectors;
    1111             :         using ScheduleManager::GetScheduleMaxValue;
    1112             :         using ScheduleManager::GetScheduleMinValue;
    1113             :         using namespace DataErrorTracking;
    1114             : 
    1115             :         static constexpr std::string_view RoutineName("GetSurfaceData: ");
    1116             : 
    1117             :         int ConstrNum;            // Construction number
    1118             :         int Found;                // For matching interzone surfaces
    1119             :         int ConstrNumFound;       // Construction number of matching interzone surface
    1120         771 :         bool NonMatch(false);     // Error for non-matching interzone surfaces
    1121             :         int MovedSurfs;           // Number of Moved Surfaces (when sorting into hierarchical structure)
    1122         771 :         bool SurfError(false);    // General Surface Error, causes fatal error at end of routine
    1123             :         int TotLay;               // Total layers in a construction
    1124             :         int TotLayFound;          // Total layers in the construction of a matching interzone surface
    1125             :         int TotDetachedFixed;     // Total Shading:Site:Detailed entries
    1126             :         int TotDetachedBldg;      // Total Shading:Building:Detailed entries
    1127             :         int TotRectDetachedFixed; // Total Shading:Site entries
    1128             :         int TotRectDetachedBldg;  // Total Shading:Building entries
    1129             :         int TotHTSurfs;           // Number of BuildingSurface:Detailed items to obtain
    1130             :         int TotDetailedWalls;     // Number of Wall:Detailed items to obtain
    1131             :         int TotDetailedRoofs;     // Number of RoofCeiling:Detailed items to obtain
    1132             :         int TotDetailedFloors;    // Number of Floor:Detailed items to obtain
    1133             :         int TotHTSubs;            // Number of FenestrationSurface:Detailed items to obtain
    1134             :         int TotShdSubs;           // Number of Shading:Zone:Detailed items to obtain
    1135             :         int TotIntMassSurfaces;   // Number of InternalMass surfaces to obtain
    1136             :         // Simple Surfaces (Rectangular)
    1137             :         int TotRectExtWalls;   // Number of Exterior Walls to obtain
    1138             :         int TotRectIntWalls;   // Number of Adiabatic Walls to obtain
    1139             :         int TotRectIZWalls;    // Number of Interzone Walls to obtain
    1140             :         int TotRectUGWalls;    // Number of Underground to obtain
    1141             :         int TotRectRoofs;      // Number of Roofs to obtain
    1142             :         int TotRectCeilings;   // Number of Adiabatic Ceilings to obtain
    1143             :         int TotRectIZCeilings; // Number of Interzone Ceilings to obtain
    1144             :         int TotRectGCFloors;   // Number of Floors with Ground Contact to obtain
    1145             :         int TotRectIntFloors;  // Number of Adiabatic Walls to obtain
    1146             :         int TotRectIZFloors;   // Number of Interzone Floors to obtain
    1147             :         int TotRectWindows;
    1148             :         int TotRectDoors;
    1149             :         int TotRectGlazedDoors;
    1150             :         int TotRectIZWindows;
    1151             :         int TotRectIZDoors;
    1152             :         int TotRectIZGlazedDoors;
    1153             :         int TotOverhangs;
    1154             :         int TotOverhangsProjection;
    1155             :         int TotFins;
    1156             :         int TotFinsProjection;
    1157         771 :         bool RelWarning(false);
    1158             :         int ConstrNumSh;      // Shaded construction number for a window
    1159             :         int LayNumOutside;    // Outside material numbers for a shaded construction
    1160             :         int BlNum;            // Blind number
    1161             :         int AddedSubSurfaces; // Subsurfaces (windows) added when windows reference Window5 Data File
    1162             :         // entries with two glazing systems
    1163             :         int NeedToAddSurfaces;    // Surfaces that will be added due to "unentered" other zone surface
    1164             :         int NeedToAddSubSurfaces; // SubSurfaces that will be added due to "unentered" other zone surface
    1165             :         int CurNewSurf;
    1166             :         int FirstTotalSurfaces;
    1167             :         int NVert;
    1168             :         int Vert;
    1169             :         int n;
    1170             :         Real64 SurfWorldAz;
    1171             :         Real64 SurfTilt;
    1172             : 
    1173             :         int MultFound;
    1174             :         int MultSurfNum;
    1175        1542 :         std::string MultString;
    1176         771 :         auto &WarningDisplayed = state.dataSurfaceGeometry->WarningDisplayed;
    1177         771 :         auto &ErrCount2 = state.dataSurfaceGeometry->ErrCount2;
    1178         771 :         auto &ErrCount3 = state.dataSurfaceGeometry->ErrCount3;
    1179         771 :         auto &ErrCount4 = state.dataSurfaceGeometry->ErrCount4;
    1180             :         bool SubSurfaceSevereDisplayed;
    1181         771 :         bool subSurfaceError(false);
    1182             :         bool errFlag;
    1183             : 
    1184             :         int iTmp1;
    1185             :         int iTmp2;
    1186             :         // unused  INTEGER :: SchID
    1187             :         int BlNumNew;
    1188         771 :         int WinShadingControlPtr(0);
    1189             :         int ErrCount;
    1190             :         bool izConstDiff;    // differences in construction for IZ surfaces
    1191             :         bool izConstDiffMsg; // display message about hb diffs only once.
    1192             : 
    1193             :         // Get the total number of surfaces to allocate derived type and for surface loops
    1194             : 
    1195         771 :         if (state.dataSurfaceGeometry->GetSurfaceDataOneTimeFlag) {
    1196           0 :             return;
    1197             :         } else {
    1198         771 :             state.dataSurfaceGeometry->GetSurfaceDataOneTimeFlag = true;
    1199             :         }
    1200             : 
    1201         771 :         GetGeometryParameters(state, ErrorsFound);
    1202             : 
    1203         771 :         if (state.dataSurface->WorldCoordSystem) {
    1204         351 :             if (state.dataHeatBal->BuildingAzimuth != 0.0) RelWarning = true;
    1205        1372 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1206        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).RelNorth != 0.0) RelWarning = true;
    1207             :             }
    1208         351 :             if (RelWarning && !WarningDisplayed) {
    1209           3 :                 ShowWarningError(
    1210             :                     state,
    1211           2 :                     std::string{RoutineName} +
    1212             :                         "World Coordinate System selected.  Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.");
    1213           1 :                 ShowContinueError(state,
    1214             :                                   "These may be used in daylighting reference point coordinate calculations but not in normal geometry inputs.");
    1215           1 :                 WarningDisplayed = true;
    1216             :             }
    1217         351 :             RelWarning = false;
    1218        1372 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1219        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginX != 0.0) RelWarning = true;
    1220        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginY != 0.0) RelWarning = true;
    1221        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginZ != 0.0) RelWarning = true;
    1222             :             }
    1223         351 :             if (RelWarning && !WarningDisplayed) {
    1224          33 :                 ShowWarningError(
    1225             :                     state,
    1226          22 :                     std::string{RoutineName} +
    1227             :                         "World Coordinate System selected.  Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.");
    1228          11 :                 ShowContinueError(state,
    1229             :                                   "These may be used in daylighting reference point coordinate calculations but not in normal geometry inputs.");
    1230          11 :                 WarningDisplayed = true;
    1231             :             }
    1232             :         }
    1233             : 
    1234         771 :         TotDetachedFixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Site:Detailed");
    1235         771 :         TotDetachedBldg = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Building:Detailed");
    1236         771 :         TotRectDetachedFixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Site");
    1237         771 :         TotRectDetachedBldg = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Building");
    1238         771 :         TotHTSurfs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "BuildingSurface:Detailed");
    1239         771 :         TotDetailedWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Detailed");
    1240         771 :         TotDetailedRoofs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "RoofCeiling:Detailed");
    1241         771 :         TotDetailedFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Detailed");
    1242         771 :         TotHTSubs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "FenestrationSurface:Detailed");
    1243         771 :         TotShdSubs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Zone:Detailed");
    1244         771 :         TotOverhangs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Overhang");
    1245         771 :         TotOverhangsProjection = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Overhang:Projection");
    1246         771 :         TotFins = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Fin");
    1247         771 :         TotFinsProjection = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Fin:Projection");
    1248         771 :         TotRectWindows = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Window");
    1249         771 :         TotRectDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Door");
    1250         771 :         TotRectGlazedDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "GlazedDoor");
    1251         771 :         TotRectIZWindows = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Window:Interzone");
    1252         771 :         TotRectIZDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Door:Interzone");
    1253         771 :         TotRectIZGlazedDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "GlazedDoor:Interzone");
    1254         771 :         TotRectExtWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Exterior");
    1255         771 :         TotRectIntWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Adiabatic");
    1256         771 :         TotRectIZWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Interzone");
    1257         771 :         TotRectUGWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Underground");
    1258         771 :         TotRectRoofs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Roof");
    1259         771 :         TotRectCeilings = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Ceiling:Adiabatic");
    1260         771 :         TotRectIZCeilings = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Ceiling:Interzone");
    1261         771 :         TotRectGCFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:GroundContact");
    1262         771 :         TotRectIntFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Adiabatic");
    1263         771 :         TotRectIZFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Interzone");
    1264             : 
    1265         771 :         state.dataSurface->TotOSC = 0;
    1266             : 
    1267         771 :         TotIntMassSurfaces = GetNumIntMassSurfaces(state);
    1268             : 
    1269        1542 :         state.dataSurface->TotSurfaces = (TotDetachedFixed + TotDetachedBldg + TotRectDetachedFixed + TotRectDetachedBldg) * 2 + TotHTSurfs +
    1270        1542 :                                          TotHTSubs + TotShdSubs * 2 + TotIntMassSurfaces + TotOverhangs * 2 + TotOverhangsProjection * 2 +
    1271        1542 :                                          TotFins * 4 + TotFinsProjection * 4 + TotDetailedWalls + TotDetailedRoofs + TotDetailedFloors +
    1272         771 :                                          TotRectWindows + TotRectDoors + TotRectGlazedDoors + TotRectIZWindows + TotRectIZDoors +
    1273         771 :                                          TotRectIZGlazedDoors + TotRectExtWalls + TotRectIntWalls + TotRectIZWalls + TotRectUGWalls + TotRectRoofs +
    1274         771 :                                          TotRectCeilings + TotRectIZCeilings + TotRectGCFloors + TotRectIntFloors + TotRectIZFloors;
    1275             : 
    1276         771 :         state.dataSurfaceGeometry->SurfaceTmp.allocate(state.dataSurface->TotSurfaces); // Allocate the Surface derived type appropriately
    1277         771 :         state.dataSurfaceGeometry->UniqueSurfaceNames.reserve(state.dataSurface->TotSurfaces);
    1278             :         // SurfaceTmp structure is allocated via derived type initialization.
    1279             : 
    1280         771 :         int NumSurfs = 0;
    1281         771 :         AddedSubSurfaces = 0;
    1282         771 :         state.dataErrTracking->AskForSurfacesReport = true;
    1283             : 
    1284         771 :         GetDetShdSurfaceData(state, ErrorsFound, NumSurfs, TotDetachedFixed, TotDetachedBldg);
    1285             : 
    1286         771 :         GetRectDetShdSurfaceData(state, ErrorsFound, NumSurfs, TotRectDetachedFixed, TotRectDetachedBldg);
    1287             : 
    1288        1542 :         GetHTSurfaceData(state,
    1289             :                          ErrorsFound,
    1290             :                          NumSurfs,
    1291             :                          TotHTSurfs,
    1292             :                          TotDetailedWalls,
    1293             :                          TotDetailedRoofs,
    1294             :                          TotDetailedFloors,
    1295         771 :                          state.dataSurfaceGeometry->BaseSurfCls,
    1296         771 :                          state.dataSurfaceGeometry->BaseSurfIDs,
    1297             :                          NeedToAddSurfaces);
    1298             : 
    1299         771 :         GetRectSurfaces(state,
    1300             :                         ErrorsFound,
    1301             :                         NumSurfs,
    1302             :                         TotRectExtWalls,
    1303             :                         TotRectIntWalls,
    1304             :                         TotRectIZWalls,
    1305             :                         TotRectUGWalls,
    1306             :                         TotRectRoofs,
    1307             :                         TotRectCeilings,
    1308             :                         TotRectIZCeilings,
    1309             :                         TotRectGCFloors,
    1310             :                         TotRectIntFloors,
    1311             :                         TotRectIZFloors,
    1312         771 :                         state.dataSurfaceGeometry->BaseSurfIDs,
    1313             :                         NeedToAddSurfaces);
    1314             : 
    1315        1542 :         GetHTSubSurfaceData(state,
    1316             :                             ErrorsFound,
    1317             :                             NumSurfs,
    1318             :                             TotHTSubs,
    1319         771 :                             state.dataSurfaceGeometry->SubSurfCls,
    1320         771 :                             state.dataSurfaceGeometry->SubSurfIDs,
    1321             :                             AddedSubSurfaces,
    1322             :                             NeedToAddSubSurfaces);
    1323             : 
    1324         771 :         GetRectSubSurfaces(state,
    1325             :                            ErrorsFound,
    1326             :                            NumSurfs,
    1327             :                            TotRectWindows,
    1328             :                            TotRectDoors,
    1329             :                            TotRectGlazedDoors,
    1330             :                            TotRectIZWindows,
    1331             :                            TotRectIZDoors,
    1332             :                            TotRectIZGlazedDoors,
    1333         771 :                            state.dataSurfaceGeometry->SubSurfIDs,
    1334             :                            AddedSubSurfaces,
    1335             :                            NeedToAddSubSurfaces);
    1336             : 
    1337         771 :         GetAttShdSurfaceData(state, ErrorsFound, NumSurfs, TotShdSubs);
    1338             : 
    1339         771 :         GetSimpleShdSurfaceData(state, ErrorsFound, NumSurfs, TotOverhangs, TotOverhangsProjection, TotFins, TotFinsProjection);
    1340             : 
    1341         771 :         GetIntMassSurfaceData(state, ErrorsFound, NumSurfs);
    1342             : 
    1343         771 :         state.dataSurface->TotSurfaces = NumSurfs + AddedSubSurfaces + NeedToAddSurfaces + NeedToAddSubSurfaces;
    1344             : 
    1345         771 :         if (ErrorsFound) {
    1346           0 :             ShowFatalError(state, std::string{RoutineName} + "Errors discovered, program terminates.");
    1347             :         }
    1348             : 
    1349         771 :         state.dataSurface->Surface.allocate(state.dataSurface->TotSurfaces); // Allocate the Surface derived type appropriately
    1350         771 :         state.dataSurface->SurfaceWindow.allocate(state.dataSurface->TotSurfaces);
    1351         771 :         AllocateSurfaceArrays(state);
    1352         771 :         AllocateSurfaceWindows(state, state.dataSurface->TotSurfaces);
    1353             : 
    1354             :         // Have to make room for added surfaces, if needed
    1355         771 :         FirstTotalSurfaces = NumSurfs + AddedSubSurfaces;
    1356         771 :         if (NeedToAddSurfaces + NeedToAddSubSurfaces > 0) {
    1357          30 :             state.dataSurfaceGeometry->SurfaceTmp.redimension(state.dataSurface->TotSurfaces);
    1358             :         }
    1359             : 
    1360             :         // add the "need to add" surfaces
    1361             :         // Debug    write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces
    1362         771 :         if (NeedToAddSurfaces + NeedToAddSubSurfaces > 0) CurNewSurf = FirstTotalSurfaces;
    1363       44165 :         for (int SurfNum = 1; SurfNum <= FirstTotalSurfaces; ++SurfNum) {
    1364       43394 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != UnenteredAdjacentZoneSurface) continue;
    1365             :             // Need to add surface
    1366         368 :             ++CurNewSurf;
    1367             :             // Debug    write(outputfiledebug,*) ' adding surface=',curnewsurf
    1368         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1369             :             //  Basic parameters are the same for both surfaces.
    1370        1104 :             Found = UtilityRoutines::FindItemInList(
    1371        1104 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    1372         368 :             if (Found == 0) continue;
    1373         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = Found;
    1374         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataHeatBal->Zone(Found).Name;
    1375             :             // Reverse Construction
    1376         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction =
    1377         368 :                 AssignReverseConstructionNumber(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction, SurfError);
    1378         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConstructionStoredInputValue =
    1379         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction;
    1380             :             // Reverse Vertices
    1381         368 :             NVert = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
    1382        1840 :             for (Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) {
    1383        1472 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex(Vert) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NVert);
    1384        1472 :                 --NVert;
    1385             :             }
    1386         368 :             if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides > 2) {
    1387         736 :                 CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
    1388         368 :                                        state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
    1389         368 :                                        state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector);
    1390         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea =
    1391         368 :                     VecLength(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector);
    1392         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea;
    1393         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
    1394         736 :                 CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
    1395         368 :                                                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
    1396         368 :                                                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector);
    1397        2208 :                 DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
    1398         368 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
    1399             :                                         SurfWorldAz,
    1400             :                                         SurfTilt,
    1401         368 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsx,
    1402         368 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsy,
    1403         368 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsz,
    1404         368 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea,
    1405         368 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector);
    1406         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Azimuth = SurfWorldAz;
    1407         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt = SurfTilt;
    1408         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConvOrientation =
    1409         368 :                     ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt);
    1410             : 
    1411             :                 // Sine and cosine of azimuth and tilt
    1412         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
    1413         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
    1414         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
    1415         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
    1416             :                 // Outward normal unit vector (pointing away from room)
    1417         736 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec =
    1418         736 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector;
    1419        1472 :                 for (n = 1; n <= 3; ++n) {
    1420        1104 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) - 1.0) < 1.e-06)
    1421          86 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = +1.0;
    1422        1104 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) + 1.0) < 1.e-06)
    1423         240 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = -1.0;
    1424        1104 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n)) < 1.e-06)
    1425         694 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = 0.0;
    1426             :                 }
    1427             : 
    1428             :                 // Can perform tests on this surface here
    1429         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky =
    1430         368 :                     0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
    1431         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGround =
    1432         368 :                     0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
    1433             : 
    1434             :                 // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    1435             :                 // surfaces
    1436         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky;
    1437         368 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGroundIR =
    1438         368 :                     0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
    1439             :             }
    1440             : 
    1441             :             // Change Name
    1442         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name = "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    1443             :             // Debug   write(outputfiledebug,*) ' new surf name=',TRIM(SurfaceTmp(CurNewSurf)%Name)
    1444             :             // Debug   write(outputfiledebug,*) ' new surf in zone=',TRIM(surfacetmp(curnewsurf)%zoneName)
    1445         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = UnreconciledZoneSurface;
    1446         368 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    1447         368 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    1448         368 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name;
    1449        1009 :             if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Roof ||
    1450         387 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Wall ||
    1451          19 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Floor) {
    1452             :                 // base surface
    1453         364 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof) {
    1454          95 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Floor;
    1455             :                     // Debug          write(outputfiledebug,*) ' new surfaces is a floor'
    1456         269 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor) {
    1457          15 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Roof;
    1458             :                     // Debug          write(outputfiledebug,*) ' new surfaces is a roof'
    1459             :                 }
    1460         364 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = CurNewSurf;
    1461         364 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name;
    1462             :                 // Debug        write(outputfiledebug,*) ' basesurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
    1463             :             } else {
    1464             :                 // subsurface
    1465           8 :                 Found = UtilityRoutines::FindItemInList("iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    1466           4 :                                                         state.dataSurfaceGeometry->SurfaceTmp,
    1467           4 :                                                         FirstTotalSurfaces + CurNewSurf - 1);
    1468           4 :                 if (Found > 0) {
    1469           8 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName =
    1470          12 :                         "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
    1471           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = Found;
    1472           4 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
    1473           7 :                     if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Window ||
    1474           3 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::GlassDoor) {
    1475           2 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -=
    1476           2 :                             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area / state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Multiplier;
    1477             :                     } else { // Door, TDD:Diffuser, TDD:DOME
    1478           2 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
    1479             :                     }
    1480           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    1481           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    1482           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    1483           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    1484           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
    1485           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
    1486           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
    1487             :                     // Debug        write(outputfiledebug,*) ' subsurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
    1488             :                     // Debug        write(outputfiledebug,*) ' subsurf, basesurf=',TRIM('iz-'//SurfaceTmp(SurfNum)%BaseSurfName)
    1489             :                 } else {
    1490           0 :                     ShowSevereError(state,
    1491           0 :                                     std::string{RoutineName} + "Adding unentered subsurface, could not find base surface=" + "iz-" +
    1492           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName);
    1493           0 :                     SurfError = true;
    1494             :                 }
    1495             :             }
    1496             :         }
    1497             :         //**********************************************************************************
    1498             :         // After all of the surfaces have been defined then the base surfaces for the
    1499             :         // sub-surfaces can be defined.  Loop through surfaces and match with the sub-surface
    1500             :         // names.
    1501       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1502       43762 :             if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) continue;
    1503             : 
    1504             :             // why are we doing this again?  this should have already been done.
    1505       42220 :             if (UtilityRoutines::SameString(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    1506       42220 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) {
    1507       35778 :                 Found = SurfNum;
    1508             :             } else {
    1509       12884 :                 Found = UtilityRoutines::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    1510        6442 :                                                         state.dataSurfaceGeometry->SurfaceTmp,
    1511        6442 :                                                         state.dataSurface->TotSurfaces);
    1512             :             }
    1513       42220 :             if (Found > 0) {
    1514       42220 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
    1515       42220 :                 if (SurfNum != Found) { // for subsurfaces
    1516        6442 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) ++state.dataSurfaceGeometry->SurfaceTmp(Found).NumSubSurfaces;
    1517       12884 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class < SurfaceClass::Window ||
    1518        6442 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class > SurfaceClass::TDD_Diffuser) {
    1519           0 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::None) {
    1520           0 :                             ShowSevereError(state,
    1521           0 :                                             std::string{RoutineName} +
    1522           0 :                                                 "Invalid SubSurface detected, Surface=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    1523             :                         } else {
    1524           0 :                             ShowSevereError(state,
    1525           0 :                                             std::string{RoutineName} + "Invalid SubSurface detected, Surface=" +
    1526           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + ", class=" +
    1527           0 :                                                 state.dataSurfaceGeometry->BaseSurfCls(int(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class)) +
    1528             :                                                 " invalid class for subsurface");
    1529           0 :                             SurfError = true;
    1530             :                         }
    1531             :                     }
    1532             :                 }
    1533             :             }
    1534             : 
    1535             :         } // ...end of the Surface DO loop for finding BaseSurf
    1536             :         //**********************************************************************************
    1537             :         // The surfaces need to be hierarchical by space.  Input is allowed to be in any order.  In
    1538             :         // this section the surfaces are reordered into:
    1539             :         //    All shadowing surfaces (if mirrored, Mir- surface follows immediately after original)
    1540             :         //      Shading:Site
    1541             :         //      Shading:Building
    1542             :         //      Shading:space (and variants)
    1543             :         //    For each space:
    1544             :         //      Walls
    1545             :         //      Floors
    1546             :         //      Roofs/Ceilings
    1547             :         //      Internal Mass
    1548             :         //      Non-Window subsurfaces (including doors)
    1549             :         //      Window subsurfaces (including TubularDaylightingDiffusers)
    1550             :         //      TubularDaylightingDomes
    1551             :         //    After reordering, MovedSurfs should equal TotSurfaces
    1552             : 
    1553             :         // For reporting purposes, the legacy surface order is also saved in DataSurfaces::AllSurfaceListReportOrder:
    1554             :         //    All shadowing surfaces (if mirrored, Mir- surface follows immediately after original)
    1555             :         //      Shading:Site
    1556             :         //      Shading:Building
    1557             :         //      Shading:Zone (and variants)
    1558             :         //    For each zone:
    1559             :         //      Walls
    1560             :         //        subsurfaces for each wall (windows, doors, in input order, not sorted) follow the base surface
    1561             :         //      Floors
    1562             :         //        subsurfaces for each floor (windows, doors, in input order, not sorted) follow the base surface
    1563             :         //      Roofs/Ceilings
    1564             :         //        subsurfaces for each roof/ceiling (windows, doors, in input order, not sorted) follow the base surface
    1565             :         //      Internal Mass
    1566             :         //    After reordering, MovedSurfs should equal TotSurfaces
    1567             : 
    1568         771 :         MovedSurfs = 0;
    1569        1542 :         Array1D<bool> SurfaceTmpClassMoved; // Tmp class is moved
    1570         771 :         SurfaceTmpClassMoved.dimension(state.dataSurface->TotSurfaces, false);
    1571         771 :         state.dataSurface->AllSurfaceListReportOrder.reserve(state.dataSurface->TotSurfaces);
    1572             : 
    1573         771 :         CreateMissingSpaces(state, state.dataSurfaceGeometry->SurfaceTmp);
    1574             : 
    1575             :         // Old SurfNum to New SurfNum
    1576             :         // Old = order in state.dataSurfaceGeometry->SurfaceTmp
    1577             :         // New = order in state.dataSurface->Surface
    1578        1542 :         EPVector<int> oldToNewSurfNums;
    1579         771 :         oldToNewSurfNums.resize(state.dataSurface->TotSurfaces, -1);
    1580             : 
    1581             :         // Move all shading Surfaces to Front
    1582       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1583      131186 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F &&
    1584       87384 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_B &&
    1585       43622 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Shading)
    1586       42220 :                 continue;
    1587             : 
    1588             :             //  A shading surface
    1589        1542 :             ++MovedSurfs;
    1590             :             // Store list of moved surface numbers in reporting order
    1591        1542 :             state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1592        1542 :             SurfaceTmpClassMoved(SurfNum) = true; //'Moved'
    1593        1542 :             state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1594        1542 :             oldToNewSurfNums(SurfNum) = MovedSurfs;
    1595             :         }
    1596             : 
    1597             :         //  For each zone
    1598             : 
    1599        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1600        9632 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    1601             :                 // Group air boundary surfaces first within each space
    1602     1205959 :                 for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1603     1201141 :                     if (SurfaceTmpClassMoved(SurfNum)) continue;
    1604      617525 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
    1605       42220 :                     int constNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    1606       42220 :                     if (constNum == 0) continue;
    1607       42220 :                     if (!state.dataConstruction->Construct(constNum).TypeIsAirBoundary) continue;
    1608             : 
    1609             :                     //  An air boundary surface
    1610          14 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsAirBoundarySurf = true;
    1611          14 :                     ++MovedSurfs;
    1612          14 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1613             :                     //  If base Surface Type (Wall, Floor, Roof/Ceiling)
    1614          28 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(1)) ||
    1615          14 :                         (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(2)) ||
    1616           0 :                         (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(3))) {
    1617             :                         // Store list of moved surface numbers in reporting order. We use the old position, we'll reconcile later
    1618             :                         // We don't do it for Air Door/Air Windows yet, we want them listed below each base surf they belong to
    1619          14 :                         state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1620             :                     }
    1621          14 :                     oldToNewSurfNums(SurfNum) = MovedSurfs;
    1622          14 :                     SurfaceTmpClassMoved(SurfNum) = true; //'Moved'
    1623             :                 }
    1624             : 
    1625             :                 //  For each Base Surface Type (Wall, Floor, Roof/Ceiling) - put these first
    1626             : 
    1627       19272 :                 for (int Loop = 1; Loop <= 3; ++Loop) {
    1628             : 
    1629     3617877 :                     for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1630             : 
    1631     3603423 :                         if (SurfaceTmpClassMoved(SurfNum)) continue;
    1632     1803075 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone == 0) continue;
    1633             : 
    1634     1803075 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
    1635       77160 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != state.dataSurfaceGeometry->BaseSurfIDs(Loop)) continue;
    1636             : 
    1637       33480 :                         ++MovedSurfs;
    1638       33480 :                         state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1639       33480 :                         oldToNewSurfNums(SurfNum) = MovedSurfs;
    1640       33480 :                         SurfaceTmpClassMoved(SurfNum) = true; // 'Moved'
    1641             :                         // Store list of moved surface numbers in order reporting order (subsurfaces follow their base surface)
    1642       33480 :                         state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1643             : 
    1644             :                         //  Find all subsurfaces to this surface - just to update Report them in order
    1645     8743378 :                         for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1646             :                             // Gotta avoid pushing myself again!
    1647     8709898 :                             if (SubSurfNum == SurfNum) continue;
    1648             :                             // We don't check if already moved, because we didn't add them to AllSurfaceListReportOrder above!
    1649     8676418 :                             if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Zone == 0) continue;
    1650     8604764 :                             if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).BaseSurf != SurfNum) continue;
    1651             :                             // Add original sub-surface numbers as placeholders in surface list for reporting
    1652        6442 :                             state.dataSurface->AllSurfaceListReportOrder.push_back(SubSurfNum);
    1653             :                         }
    1654             :                     }
    1655             :                 }
    1656             : 
    1657             :                 // Internal mass goes next
    1658     1205959 :                 for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1659             : 
    1660     1201141 :                     if (SurfaceTmpClassMoved(SurfNum)) continue;
    1661      584031 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
    1662        8726 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::IntMass) continue;
    1663        2284 :                     ++MovedSurfs;
    1664        2284 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1665        2284 :                     oldToNewSurfNums(SurfNum) = MovedSurfs;
    1666        2284 :                     SurfaceTmpClassMoved(SurfNum) = true; // 'Moved'
    1667             :                     // Store list of moved surface numbers in reporting order
    1668        2284 :                     state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1669             :                 }
    1670             : 
    1671             :                 // Opaque door goes next
    1672     1205959 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1673             : 
    1674     1201141 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1675      581747 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1676        6442 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Door) continue;
    1677             : 
    1678         466 :                     ++MovedSurfs;
    1679         466 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1680         466 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1681         466 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1682             :                 }
    1683             : 
    1684             :                 // The exterior window subsurfaces (includes SurfaceClass::Window and SurfaceClass::GlassDoor) goes next
    1685     1205959 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1686             : 
    1687     1201141 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1688      581281 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1689        5976 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).ExtBoundCond > 0) continue; // Exterior window
    1690        6487 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Window) &&
    1691         511 :                         (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::GlassDoor))
    1692           4 :                         continue;
    1693             : 
    1694        5972 :                     ++MovedSurfs;
    1695        5972 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1696        5972 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1697        5972 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1698             :                 }
    1699             : 
    1700             :                 // The interior window subsurfaces (includes SurfaceClass::Window and SurfaceClass::GlassDoor) goes next
    1701     1205959 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1702             : 
    1703     1201141 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1704      575309 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1705           4 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).ExtBoundCond <= 0) continue;
    1706           0 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Window) &&
    1707           0 :                         (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::GlassDoor))
    1708           0 :                         continue;
    1709             : 
    1710           0 :                     ++MovedSurfs;
    1711           0 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1712           0 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1713           0 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1714             :                 }
    1715             : 
    1716             :                 // The SurfaceClass::TDD_Diffuser (OriginalClass = Window) goes next
    1717     1205959 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1718             : 
    1719     1201141 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1720      575309 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1721           4 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::TDD_Diffuser) continue;
    1722             : 
    1723           2 :                     ++MovedSurfs;
    1724           2 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1725           2 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1726           2 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1727             :                 }
    1728             : 
    1729             :                 // Last but not least, SurfaceClass::TDD_Dome
    1730     1205959 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1731             : 
    1732     1201141 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1733      575307 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1734           2 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::TDD_Dome) continue;
    1735             : 
    1736           2 :                     ++MovedSurfs;
    1737           2 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1738           2 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1739           2 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1740             :                 }
    1741             :             }
    1742             :         }
    1743             : 
    1744             :         // Validity checking
    1745         771 :         assert(state.dataSurface->TotSurfaces == MovedSurfs);
    1746         771 :         assert(state.dataSurface->TotSurfaces == static_cast<int>(state.dataSurface->AllSurfaceListReportOrder.size()));
    1747         771 :         assert(state.dataSurface->TotSurfaces == static_cast<int>(oldToNewSurfNums.size()));
    1748             : 
    1749             :         // Assert validity of indices
    1750       44533 :         assert(std::find_if(state.dataSurface->AllSurfaceListReportOrder.cbegin(), state.dataSurface->AllSurfaceListReportOrder.cend(), [](int i) {
    1751             :                    return i < 1;
    1752             :                }) == state.dataSurface->AllSurfaceListReportOrder.cend());
    1753             : 
    1754       44533 :         assert(std::find_if(oldToNewSurfNums.cbegin(), oldToNewSurfNums.cend(), [](int i) { return i < 1; }) == oldToNewSurfNums.cend());
    1755             : 
    1756         771 :         if (MovedSurfs != state.dataSurface->TotSurfaces) {
    1757           0 :             ShowSevereError(
    1758             :                 state,
    1759           0 :                 format("{}Reordered # of Surfaces ({}) not = Total # of Surfaces ({})", RoutineName, MovedSurfs, state.dataSurface->TotSurfaces));
    1760           0 :             SurfError = true;
    1761           0 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfaces; ++Loop) {
    1762           0 :                 if (!SurfaceTmpClassMoved(Loop) && state.dataSurfaceGeometry->SurfaceTmp(Loop).Class == SurfaceClass::Invalid) {
    1763           0 :                     ShowSevereError(state,
    1764           0 :                                     std::string{RoutineName} + "Error in Surface= \"" + state.dataSurfaceGeometry->SurfaceTmp(Loop).Name +
    1765           0 :                                         " indicated Zone=\"" + state.dataSurfaceGeometry->SurfaceTmp(Loop).ZoneName + "\"");
    1766             :                 }
    1767             :             }
    1768           0 :             ShowWarningError(state,
    1769           0 :                              std::string{RoutineName} +
    1770             :                                  "Remaining surface checks will use \"reordered number of surfaces\", not number of original surfaces");
    1771             :         }
    1772             : 
    1773             :         // Realign the relationship: surface to base surface
    1774       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1775       43762 :             auto &movedSurf = state.dataSurface->Surface(SurfNum);
    1776       43762 :             if (movedSurf.BaseSurf > 0) {
    1777       42220 :                 int newBaseSurfNum = oldToNewSurfNums(movedSurf.BaseSurf);
    1778       42220 :                 movedSurf.BaseSurf = newBaseSurfNum;
    1779             : 
    1780       42220 :                 if (newBaseSurfNum < 1) {
    1781           0 :                     ShowFatalError(
    1782             :                         state,
    1783           0 :                         format("{}Couldn't find the new Surface Number for surface index {} named '{}'. Looking for BaseSurf old index of {}",
    1784             :                                RoutineName,
    1785             :                                SurfNum,
    1786             :                                movedSurf.Name,
    1787           0 :                                movedSurf.BaseSurf));
    1788             :                 }
    1789             :             }
    1790       43762 :             auto &reportOrderNum = state.dataSurface->AllSurfaceListReportOrder[SurfNum - 1];
    1791       43762 :             if (reportOrderNum > 0) {
    1792       43762 :                 int newReportOrderNum = oldToNewSurfNums(reportOrderNum);
    1793       43762 :                 reportOrderNum = newReportOrderNum;
    1794             :             }
    1795             :         }
    1796             : 
    1797         771 :         state.dataSurfaceGeometry->SurfaceTmp.deallocate(); // DeAllocate the Temp Surface derived type
    1798             : 
    1799         771 :         createSpaceSurfaceLists(state, ErrorsFound);
    1800             : 
    1801             :         //  For each Base Surface Type (Wall, Floor, Roof)
    1802             : 
    1803        3084 :         for (int Loop = 1; Loop <= 3; ++Loop) {
    1804      133599 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1805             : 
    1806      131286 :                 if (state.dataSurface->Surface(SurfNum).Zone == 0) continue;
    1807             : 
    1808      126660 :                 if (state.dataSurface->Surface(SurfNum).Class != state.dataSurfaceGeometry->BaseSurfIDs(Loop)) continue;
    1809             : 
    1810             :                 //  Find all subsurfaces to this surface
    1811     8744122 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1812             : 
    1813     8710628 :                     if (SurfNum == SubSurfNum) continue;
    1814     8677134 :                     if (state.dataSurface->Surface(SubSurfNum).Zone == 0) continue;
    1815     8605424 :                     if (state.dataSurface->Surface(SubSurfNum).BaseSurf != SurfNum) continue;
    1816             : 
    1817             :                     // Check facing angle of Sub compared to base
    1818        6442 :                     checkSubSurfAzTiltNorm(state, state.dataSurface->Surface(SurfNum), state.dataSurface->Surface(SubSurfNum), subSurfaceError);
    1819        6442 :                     if (subSurfaceError) SurfError = true;
    1820             :                 }
    1821             :             }
    1822             :         }
    1823             : 
    1824             :         //**********************************************************************************
    1825             :         // Now, match up interzone surfaces
    1826         771 :         NonMatch = false;
    1827         771 :         izConstDiffMsg = false;
    1828       44533 :         for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    1829             :             //  Clean up Shading Surfaces, make sure they don't go through here.
    1830       43762 :             if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    1831             :             //   If other surface, match it up
    1832             :             //  Both interzone and "internal" surfaces have this pointer set
    1833             :             //  Internal surfaces point to themselves, Interzone to another
    1834       42220 :             if (state.dataSurface->Surface(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    1835       14330 :                 if (not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) {
    1836       14330 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCondName == state.dataSurface->Surface(SurfNum).Name) {
    1837        5886 :                         Found = SurfNum;
    1838             :                     } else {
    1839       25332 :                         Found = UtilityRoutines::FindItemInList(
    1840       16888 :                             state.dataSurface->Surface(SurfNum).ExtBoundCondName, state.dataSurface->Surface, MovedSurfs);
    1841             :                     }
    1842       14330 :                     if (Found != 0) {
    1843       14330 :                         state.dataSurface->Surface(SurfNum).ExtBoundCond = Found;
    1844             :                         // Check that matching surface is also "OtherZoneSurface"
    1845       22739 :                         if (state.dataSurface->Surface(Found).ExtBoundCond <= 0 &&
    1846        8409 :                             state.dataSurface->Surface(Found).ExtBoundCond != UnreconciledZoneSurface) {
    1847           0 :                             ShowSevereError(state, std::string{RoutineName} + "Potential \"OtherZoneSurface\" is not matched correctly:");
    1848             : 
    1849           0 :                             ShowContinueError(state,
    1850           0 :                                               "Surface=" + state.dataSurface->Surface(SurfNum).Name +
    1851           0 :                                                   ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
    1852           0 :                             ShowContinueError(state,
    1853           0 :                                               "Nonmatched Other/InterZone Surface=" + state.dataSurface->Surface(Found).Name +
    1854           0 :                                                   ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
    1855           0 :                             SurfError = true;
    1856             :                         }
    1857             :                         // Check that matching interzone surface has construction with reversed layers
    1858       14330 :                         if (Found != SurfNum) { // Interzone surface
    1859             :                             // Make sure different zones too (CR 4110)
    1860        8444 :                             if (state.dataSurface->Surface(SurfNum).spaceNum == state.dataSurface->Surface(Found).spaceNum) {
    1861           3 :                                 ++ErrCount2;
    1862           3 :                                 if (ErrCount2 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    1863           6 :                                     ShowWarningError(state,
    1864           4 :                                                      std::string{RoutineName} + "CAUTION -- Interspace surfaces are occuring in the same space(s).");
    1865           2 :                                     ShowContinueError(
    1866             :                                         state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual occurrences.");
    1867             :                                 }
    1868           3 :                                 if (state.dataGlobal->DisplayExtraWarnings) {
    1869           0 :                                     ShowWarningError(state,
    1870           0 :                                                      std::string{RoutineName} + "CAUTION -- Interspace surfaces are usually in different spaces");
    1871           0 :                                     ShowContinueError(state,
    1872           0 :                                                       "Surface=" + state.dataSurface->Surface(SurfNum).Name +
    1873           0 :                                                           ", Space=" + state.dataHeatBal->space(state.dataSurface->Surface(SurfNum).spaceNum).Name +
    1874           0 :                                                           ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
    1875           0 :                                     ShowContinueError(state,
    1876           0 :                                                       "Surface=" + state.dataSurface->Surface(Found).Name +
    1877           0 :                                                           ", Space=" + state.dataHeatBal->space(state.dataSurface->Surface(Found).spaceNum).Name +
    1878           0 :                                                           ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
    1879             :                                 }
    1880             :                             }
    1881        8444 :                             ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
    1882        8444 :                             ConstrNumFound = state.dataSurface->Surface(Found).Construction;
    1883        8444 :                             if (ConstrNum <= 0 || ConstrNumFound <= 0) continue;
    1884        8444 :                             if (state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning &&
    1885           0 :                                 state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning)
    1886           0 :                                 continue;
    1887        8456 :                             if (state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning &&
    1888          12 :                                 state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning)
    1889          12 :                                 continue;
    1890        8432 :                             TotLay = state.dataConstruction->Construct(ConstrNum).TotLayers;
    1891        8432 :                             TotLayFound = state.dataConstruction->Construct(ConstrNumFound).TotLayers;
    1892        8432 :                             if (TotLay != TotLayFound) { // Different number of layers
    1893             :                                 // match on like Uvalues (nominal)
    1894           0 :                                 if (std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound)) > 0.001) {
    1895           0 :                                     ShowSevereError(state,
    1896           0 :                                                     std::string{RoutineName} + "Construction " + state.dataConstruction->Construct(ConstrNum).Name +
    1897           0 :                                                         " of interzone surface " + state.dataSurface->Surface(SurfNum).Name +
    1898           0 :                                                         " does not have the same number of layers as the construction " +
    1899           0 :                                                         state.dataConstruction->Construct(ConstrNumFound).Name + " of adjacent surface " +
    1900           0 :                                                         state.dataSurface->Surface(Found).Name);
    1901           0 :                                     if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning ||
    1902           0 :                                         !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning) {
    1903           0 :                                         ShowContinueError(state, "...this problem for this pair will not be reported again.");
    1904           0 :                                         state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning = true;
    1905           0 :                                         state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning = true;
    1906             :                                     }
    1907           0 :                                     SurfError = true;
    1908             :                                 }
    1909             :                             } else { // Same number of layers; check for reverse layers
    1910             :                                 // check layers as number of layers is the same
    1911        8432 :                                 izConstDiff = false;
    1912             :                                 // ok if same nominal U
    1913        8432 :                                 CheckForReversedLayers(state, izConstDiff, ConstrNum, ConstrNumFound, TotLay);
    1914        8434 :                                 if (izConstDiff &&
    1915           2 :                                     std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound)) > 0.001) {
    1916           0 :                                     ShowSevereError(state,
    1917           0 :                                                     std::string{RoutineName} + "Construction " + state.dataConstruction->Construct(ConstrNum).Name +
    1918           0 :                                                         " of interzone surface " + state.dataSurface->Surface(SurfNum).Name +
    1919           0 :                                                         " does not have the same materials in the reverse order as the construction " +
    1920           0 :                                                         state.dataConstruction->Construct(ConstrNumFound).Name + " of adjacent surface " +
    1921           0 :                                                         state.dataSurface->Surface(Found).Name);
    1922           0 :                                     ShowContinueError(state,
    1923             :                                                       "or the properties of the reversed layers are not correct due to differing layer front and "
    1924             :                                                       "back side values");
    1925           0 :                                     if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning ||
    1926           0 :                                         !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning) {
    1927           0 :                                         ShowContinueError(state, "...this problem for this pair will not be reported again.");
    1928           0 :                                         state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning = true;
    1929           0 :                                         state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning = true;
    1930             :                                     }
    1931           0 :                                     SurfError = true;
    1932        8432 :                                 } else if (izConstDiff) {
    1933           6 :                                     ShowWarningError(state,
    1934           4 :                                                      std::string{RoutineName} + "Construction " + state.dataConstruction->Construct(ConstrNum).Name +
    1935           6 :                                                          " of interzone surface " + state.dataSurface->Surface(SurfNum).Name +
    1936           6 :                                                          " does not have the same materials in the reverse order as the construction " +
    1937           6 :                                                          state.dataConstruction->Construct(ConstrNumFound).Name + " of adjacent surface " +
    1938           2 :                                                          state.dataSurface->Surface(Found).Name);
    1939           2 :                                     ShowContinueError(state,
    1940             :                                                       "or the properties of the reversed layers are not correct due to differing layer front and "
    1941             :                                                       "back side values");
    1942           6 :                                     ShowContinueError(
    1943             :                                         state,
    1944           4 :                                         format("...but Nominal U values are similar, diff=[{:.4R}] ... simulation proceeds.",
    1945           4 :                                                std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound))));
    1946           2 :                                     if (!izConstDiffMsg) {
    1947           2 :                                         ShowContinueError(state,
    1948             :                                                           "...if the two zones are expected to have significantly different temperatures, the proper "
    1949             :                                                           "\"reverse\" construction should be created.");
    1950           2 :                                         izConstDiffMsg = true;
    1951             :                                     }
    1952           2 :                                     if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning ||
    1953           0 :                                         !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning) {
    1954           2 :                                         ShowContinueError(state, "...this problem for this pair will not be reported again.");
    1955           2 :                                         state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning = true;
    1956           2 :                                         state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning = true;
    1957             :                                     }
    1958             :                                 }
    1959             :                             }
    1960             : 
    1961             :                             // If significantly different areas -- this would not be good
    1962       16864 :                             MultFound = state.dataHeatBal->Zone(state.dataSurface->Surface(Found).Zone).Multiplier *
    1963        8432 :                                         state.dataHeatBal->Zone(state.dataSurface->Surface(Found).Zone).ListMultiplier;
    1964       16864 :                             MultSurfNum = state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).Multiplier *
    1965        8432 :                                           state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).ListMultiplier;
    1966        8432 :                             if (state.dataSurface->Surface(Found).Area > 0.0) {
    1967       33728 :                                 if (std::abs((state.dataSurface->Surface(Found).Area * MultFound -
    1968       16864 :                                               state.dataSurface->Surface(SurfNum).Area * MultSurfNum) /
    1969       16864 :                                              state.dataSurface->Surface(Found).Area * MultFound) > 0.02) { // 2% difference in areas
    1970           0 :                                     ++ErrCount4;
    1971           0 :                                     if (ErrCount4 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    1972           0 :                                         ShowWarningError(state,
    1973           0 :                                                          std::string{RoutineName} + "InterZone Surface Areas do not match as expected and "
    1974             :                                                                                     "might not satisfy conservation of energy:");
    1975           0 :                                         ShowContinueError(
    1976             :                                             state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual mismatches.");
    1977             :                                     }
    1978           0 :                                     if (state.dataGlobal->DisplayExtraWarnings) {
    1979           0 :                                         ShowWarningError(state,
    1980           0 :                                                          std::string{RoutineName} + "InterZone Surface Areas do not match as expected and "
    1981             :                                                                                     "might not satisfy conservation of energy:");
    1982             : 
    1983           0 :                                         if (MultFound == 1 && MultSurfNum == 1) {
    1984           0 :                                             ShowContinueError(state,
    1985           0 :                                                               format("  Area={:.1T} in Surface={}, Zone={}",
    1986           0 :                                                                      state.dataSurface->Surface(SurfNum).Area,
    1987           0 :                                                                      state.dataSurface->Surface(SurfNum).Name,
    1988           0 :                                                                      state.dataSurface->Surface(SurfNum).ZoneName));
    1989           0 :                                             ShowContinueError(state,
    1990           0 :                                                               format("  Area={:.1T} in Surface={}, Zone={}",
    1991           0 :                                                                      state.dataSurface->Surface(Found).Area,
    1992           0 :                                                                      state.dataSurface->Surface(Found).Name,
    1993           0 :                                                                      state.dataSurface->Surface(Found).ZoneName));
    1994             :                                         } else { // Show multiplier info
    1995           0 :                                             ShowContinueError(state,
    1996           0 :                                                               format("  Area={:.1T}, Multipliers={}, Total Area={:.1T} in Surface={} Zone={}",
    1997           0 :                                                                      state.dataSurface->Surface(SurfNum).Area,
    1998             :                                                                      MultSurfNum,
    1999           0 :                                                                      state.dataSurface->Surface(SurfNum).Area * MultSurfNum,
    2000           0 :                                                                      state.dataSurface->Surface(SurfNum).Name,
    2001           0 :                                                                      state.dataSurface->Surface(SurfNum).ZoneName));
    2002             : 
    2003           0 :                                             ShowContinueError(state,
    2004           0 :                                                               format("  Area={:.1T}, Multipliers={}, Total Area={:.1T} in Surface={} Zone={}",
    2005           0 :                                                                      state.dataSurface->Surface(Found).Area,
    2006             :                                                                      MultFound,
    2007           0 :                                                                      state.dataSurface->Surface(Found).Area * MultFound,
    2008           0 :                                                                      state.dataSurface->Surface(Found).Name,
    2009           0 :                                                                      state.dataSurface->Surface(Found).ZoneName));
    2010             :                                         }
    2011             :                                     }
    2012             :                                 }
    2013             :                             }
    2014             :                             // Check opposites Azimuth and Tilt
    2015             :                             // Tilt
    2016        8432 :                             if (std::abs(std::abs(state.dataSurface->Surface(Found).Tilt + state.dataSurface->Surface(SurfNum).Tilt) - 180.0) > 1.0) {
    2017           0 :                                 ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Tilts do not match as expected.");
    2018           0 :                                 ShowContinueError(state,
    2019           0 :                                                   format("  Tilt={:.1T} in Surface={}, Zone={}",
    2020           0 :                                                          state.dataSurface->Surface(SurfNum).Tilt,
    2021           0 :                                                          state.dataSurface->Surface(SurfNum).Name,
    2022           0 :                                                          state.dataSurface->Surface(SurfNum).ZoneName));
    2023           0 :                                 ShowContinueError(state,
    2024           0 :                                                   format("  Tilt={:.1T} in Surface={}, Zone={}",
    2025           0 :                                                          state.dataSurface->Surface(Found).Tilt,
    2026           0 :                                                          state.dataSurface->Surface(Found).Name,
    2027           0 :                                                          state.dataSurface->Surface(Found).ZoneName));
    2028             :                             }
    2029             :                             // check surface class match.  interzone surface.
    2030             : 
    2031       22458 :                             if ((state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Wall &&
    2032       16864 :                                  state.dataSurface->Surface(Found).Class != SurfaceClass::Wall) ||
    2033       11270 :                                 (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall &&
    2034        2838 :                                  state.dataSurface->Surface(Found).Class == SurfaceClass::Wall)) {
    2035           0 :                                 ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Classes do not match as expected.");
    2036           0 :                                 ShowContinueError(state,
    2037           0 :                                                   "Surface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2038           0 :                                                       "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(SurfNum).Class));
    2039           0 :                                 ShowContinueError(state,
    2040           0 :                                                   "Adjacent Surface=\"" + state.dataSurface->Surface(Found).Name +
    2041           0 :                                                       "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(Found).Class));
    2042           0 :                                 ShowContinueError(state, "Other errors/warnings may follow about these surfaces.");
    2043             :                             }
    2044       18257 :                             if ((state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Roof &&
    2045       16864 :                                  state.dataSurface->Surface(Found).Class != SurfaceClass::Floor) ||
    2046       15471 :                                 (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof &&
    2047        7039 :                                  state.dataSurface->Surface(Found).Class == SurfaceClass::Floor)) {
    2048           0 :                                 ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Classes do not match as expected.");
    2049           0 :                                 ShowContinueError(state,
    2050           0 :                                                   "Surface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2051           0 :                                                       "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(SurfNum).Class));
    2052           0 :                                 ShowContinueError(state,
    2053           0 :                                                   "Adjacent Surface=\"" + state.dataSurface->Surface(Found).Name +
    2054           0 :                                                       "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(Found).Class));
    2055           0 :                                 ShowContinueError(state, "Other errors/warnings may follow about these surfaces.");
    2056             :                             }
    2057       15471 :                             if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof &&
    2058        7039 :                                 state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) {
    2059             :                                 // Walls, Windows, Doors, Glass Doors
    2060        5634 :                                 if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) {
    2061             :                                     // Surface is a Door, Window or Glass Door
    2062          40 :                                     if (state.dataSurface->Surface(SurfNum).BaseSurf == 0) continue; // error detected elsewhere
    2063          79 :                                     if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Class == SurfaceClass::Roof ||
    2064          39 :                                         state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Class == SurfaceClass::Floor)
    2065           2 :                                         continue;
    2066             :                                 }
    2067       11264 :                                 if (std::abs(std::abs(state.dataSurface->Surface(SurfNum).Azimuth - state.dataSurface->Surface(Found).Azimuth) -
    2068        5632 :                                              180.0) > 1.0) {
    2069           0 :                                     if (std::abs(state.dataSurface->Surface(SurfNum).SinTilt) > 0.5 || state.dataGlobal->DisplayExtraWarnings) {
    2070             :                                         // if horizontal surfaces, then these are windows/doors/etc in those items.
    2071           0 :                                         ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Azimuths do not match as expected.");
    2072           0 :                                         ShowContinueError(state,
    2073           0 :                                                           format("  Azimuth={:.1T}, Tilt={:.1T}, in Surface={}, Zone={}",
    2074           0 :                                                                  state.dataSurface->Surface(SurfNum).Azimuth,
    2075           0 :                                                                  state.dataSurface->Surface(SurfNum).Tilt,
    2076           0 :                                                                  state.dataSurface->Surface(SurfNum).Name,
    2077           0 :                                                                  state.dataSurface->Surface(SurfNum).ZoneName));
    2078           0 :                                         ShowContinueError(state,
    2079           0 :                                                           format("  Azimuth={:.1T}, Tilt={:.1T}, in Surface={}, Zone={}",
    2080           0 :                                                                  state.dataSurface->Surface(Found).Azimuth,
    2081           0 :                                                                  state.dataSurface->Surface(Found).Tilt,
    2082           0 :                                                                  state.dataSurface->Surface(Found).Name,
    2083           0 :                                                                  state.dataSurface->Surface(Found).ZoneName));
    2084           0 :                                         ShowContinueError(
    2085           0 :                                             state, "..surface class of first surface=" + cSurfaceClass(state.dataSurface->Surface(SurfNum).Class));
    2086           0 :                                         ShowContinueError(
    2087           0 :                                             state, "..surface class of second surface=" + cSurfaceClass(state.dataSurface->Surface(Found).Class));
    2088             :                                     }
    2089             :                                 }
    2090             :                             }
    2091             : 
    2092             :                             // Make sure exposures (Sun, Wind) are the same.....and are "not"
    2093        8430 :                             if (state.dataSurface->Surface(SurfNum).ExtSolar || state.dataSurface->Surface(Found).ExtSolar) {
    2094           0 :                                 ShowWarningError(state,
    2095           0 :                                                  std::string{RoutineName} + "Interzone surfaces cannot be \"SunExposed\" -- removing SunExposed");
    2096           0 :                                 ShowContinueError(state,
    2097           0 :                                                   "  Surface=" + state.dataSurface->Surface(SurfNum).Name +
    2098           0 :                                                       ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
    2099           0 :                                 ShowContinueError(state,
    2100           0 :                                                   "  Surface=" + state.dataSurface->Surface(Found).Name +
    2101           0 :                                                       ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
    2102           0 :                                 state.dataSurface->Surface(SurfNum).ExtSolar = false;
    2103           0 :                                 state.dataSurface->Surface(Found).ExtSolar = false;
    2104             :                             }
    2105        8430 :                             if (state.dataSurface->Surface(SurfNum).ExtWind || state.dataSurface->Surface(Found).ExtWind) {
    2106           0 :                                 ShowWarningError(state,
    2107           0 :                                                  std::string{RoutineName} + "Interzone surfaces cannot be \"WindExposed\" -- removing WindExposed");
    2108           0 :                                 ShowContinueError(state,
    2109           0 :                                                   "  Surface=" + state.dataSurface->Surface(SurfNum).Name +
    2110           0 :                                                       ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
    2111           0 :                                 ShowContinueError(state,
    2112           0 :                                                   "  Surface=" + state.dataSurface->Surface(Found).Name +
    2113           0 :                                                       ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
    2114           0 :                                 state.dataSurface->Surface(SurfNum).ExtWind = false;
    2115           0 :                                 state.dataSurface->Surface(Found).ExtWind = false;
    2116             :                             }
    2117             :                         }
    2118             :                         // Set opposing surface back to this one (regardless of error)
    2119       14316 :                         state.dataSurface->Surface(Found).ExtBoundCond = SurfNum;
    2120             :                         // Check subsurfaces...  make sure base surface is also an interzone surface
    2121       14316 :                         if (state.dataSurface->Surface(SurfNum).BaseSurf != SurfNum) { // Subsurface
    2122          76 :                             if ((state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) &&
    2123          38 :                                 not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) {
    2124             :                                 // if not internal subsurface
    2125          76 :                                 if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond ==
    2126          38 :                                     state.dataSurface->Surface(SurfNum).BaseSurf) {
    2127             :                                     // base surface is not interzone surface
    2128           0 :                                     ShowSevereError(state,
    2129           0 :                                                     std::string{RoutineName} + "SubSurface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2130             :                                                         "\" is an interzone subsurface.");
    2131           0 :                                     ShowContinueError(state,
    2132           0 :                                                       "..but the Base Surface is not an interzone surface, Surface=\"" +
    2133           0 :                                                           state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\".");
    2134           0 :                                     SurfError = true;
    2135             :                                 }
    2136             :                             }
    2137             :                         }
    2138             :                     } else {
    2139             :                         //  Seems unlikely that an internal surface would be missing itself, so this message
    2140             :                         //  only indicates for adjacent (interzone) surfaces.
    2141           0 :                         ShowSevereError(state,
    2142           0 :                                         std::string{RoutineName} +
    2143           0 :                                             "Adjacent Surface not found: " + state.dataSurface->Surface(SurfNum).ExtBoundCondName +
    2144           0 :                                             " adjacent to surface " + state.dataSurface->Surface(SurfNum).Name);
    2145           0 :                         NonMatch = true;
    2146           0 :                         SurfError = true;
    2147             :                     }
    2148           0 :                 } else if (state.dataSurface->Surface(SurfNum).BaseSurf != SurfNum) { // Subsurface
    2149           0 :                     if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond > 0 &&
    2150           0 :                         state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond !=
    2151           0 :                             state.dataSurface->Surface(SurfNum).BaseSurf) { // If Interzone surface, subsurface must be also.
    2152           0 :                         ShowSevereError(state, std::string{RoutineName} + "SubSurface on Interzone Surface must be an Interzone SubSurface.");
    2153           0 :                         ShowContinueError(state, "...OutsideFaceEnvironment is blank, in Surface=" + state.dataSurface->Surface(SurfNum).Name);
    2154           0 :                         SurfError = true;
    2155             :                     } else {
    2156           0 :                         ++ErrCount3;
    2157           0 :                         if (ErrCount3 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2158           0 :                             ShowWarningError(state, std::string{RoutineName} + "Blank name for Outside Boundary Condition Objects.");
    2159           0 :                             ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
    2160             :                         }
    2161           0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    2162           0 :                             ShowWarningError(state,
    2163           0 :                                              std::string{RoutineName} + "Blank name for Outside Boundary Condition Object, in surface=" +
    2164           0 :                                                  state.dataSurface->Surface(SurfNum).Name);
    2165           0 :                             ShowContinueError(
    2166           0 :                                 state, "Resetting this surface to be an internal zone surface, zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
    2167             :                         }
    2168           0 :                         state.dataSurface->Surface(SurfNum).ExtBoundCondName = state.dataSurface->Surface(SurfNum).Name;
    2169           0 :                         state.dataSurface->Surface(SurfNum).ExtBoundCond = SurfNum;
    2170             :                     }
    2171             :                 } else {
    2172           0 :                     ++ErrCount3;
    2173           0 :                     if (ErrCount3 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2174           0 :                         ShowSevereError(state, std::string{RoutineName} + "Blank name for Outside Boundary Condition Objects.");
    2175           0 :                         ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
    2176             :                     }
    2177           0 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    2178           0 :                         ShowWarningError(state,
    2179           0 :                                          std::string{RoutineName} + "Blank name for Outside Boundary Condition Object, in surface=" +
    2180           0 :                                              state.dataSurface->Surface(SurfNum).Name);
    2181           0 :                         ShowContinueError(state,
    2182           0 :                                           "Resetting this surface to be an internal zone (adiabatic) surface, zone=" +
    2183           0 :                                               state.dataSurface->Surface(SurfNum).ZoneName);
    2184             :                     }
    2185           0 :                     state.dataSurface->Surface(SurfNum).ExtBoundCondName = state.dataSurface->Surface(SurfNum).Name;
    2186           0 :                     state.dataSurface->Surface(SurfNum).ExtBoundCond = SurfNum;
    2187           0 :                     SurfError = true;
    2188             :                 }
    2189             :             }
    2190             : 
    2191             :         } // ...end of the Surface DO loop for finding BaseSurf
    2192         771 :         if (NonMatch) {
    2193           0 :             ShowSevereError(state, std::string{RoutineName} + "Non matching interzone surfaces found");
    2194             :         }
    2195             : 
    2196             :         //**********************************************************************************
    2197             :         // Warn about interzone surfaces that have adiabatic windows/vice versa
    2198         771 :         SubSurfaceSevereDisplayed = false;
    2199       44533 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2200       43762 :             if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    2201       42220 :             if (state.dataSurface->Surface(SurfNum).BaseSurf == SurfNum) continue; // base surface
    2202             :             // not base surface.  Check it.
    2203        6442 :             if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond <= 0) { // exterior or other base surface
    2204       12724 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond !=
    2205        6362 :                     state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) { // should match base surface
    2206           0 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCond == SurfNum) {
    2207           0 :                         ShowSevereError(
    2208             :                             state,
    2209           0 :                             std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2210           0 :                                 "\" exterior condition [adiabatic surface] in a base surface=\"" +
    2211           0 :                                 state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
    2212           0 :                                 cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
    2213           0 :                         SurfError = true;
    2214           0 :                     } else if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) {
    2215           0 :                         ShowSevereError(
    2216             :                             state,
    2217           0 :                             std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2218           0 :                                 "\" exterior condition [interzone surface] in a base surface=\"" +
    2219           0 :                                 state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
    2220           0 :                                 cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
    2221           0 :                         SurfError = true;
    2222           0 :                     } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond == OtherSideCondModeledExt) {
    2223           0 :                         ShowWarningError(
    2224             :                             state,
    2225           0 :                             std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name + "\" exterior condition [" +
    2226           0 :                                 cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond) + "] in a base surface=\"" +
    2227           0 :                                 state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
    2228           0 :                                 cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
    2229           0 :                         ShowContinueError(state, "...SubSurface will not use the exterior condition model of the base surface.");
    2230             :                     } else {
    2231           0 :                         ShowSevereError(
    2232             :                             state,
    2233           0 :                             std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name + "\" exterior condition [" +
    2234           0 :                                 cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond) + "] in a base surface=\"" +
    2235           0 :                                 state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
    2236           0 :                                 cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
    2237           0 :                         SurfError = true;
    2238             :                     }
    2239           0 :                     if (!SubSurfaceSevereDisplayed && SurfError) {
    2240           0 :                         ShowContinueError(state, "...calculations for heat balance would be compromised.");
    2241           0 :                         SubSurfaceSevereDisplayed = true;
    2242             :                     }
    2243             :                 }
    2244         160 :             } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).BaseSurf ==
    2245          80 :                        state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) {
    2246             :                 // adiabatic surface. make sure subsurfaces match
    2247           0 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) { // not adiabatic surface
    2248           0 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) {
    2249           0 :                         ShowSevereError(state,
    2250           0 :                                         std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2251           0 :                                             "\" exterior condition [interzone surface] in a base surface=\"" +
    2252           0 :                                             state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name +
    2253             :                                             "\" with exterior condition [adiabatic surface]");
    2254             :                     } else {
    2255           0 :                         ShowSevereError(state,
    2256           0 :                                         std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2257           0 :                                             "\" exterior condition [" + cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond) +
    2258           0 :                                             "] in a base surface=\"" + state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name +
    2259             :                                             "\" with exterior condition [adiabatic surface]");
    2260             :                     }
    2261           0 :                     if (!SubSurfaceSevereDisplayed) {
    2262           0 :                         ShowContinueError(state, "...calculations for heat balance would be compromised.");
    2263           0 :                         SubSurfaceSevereDisplayed = true;
    2264             :                     }
    2265           0 :                     SurfError = true;
    2266             :                 }
    2267          80 :             } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond > 0) { // interzone surface
    2268          80 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond == SurfNum) {
    2269           0 :                     ShowSevereError(state,
    2270           0 :                                     std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2271           0 :                                         "\" is an adiabatic surface in an Interzone base surface=\"" +
    2272           0 :                                         state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\"");
    2273           0 :                     if (!SubSurfaceSevereDisplayed) {
    2274           0 :                         ShowContinueError(state, "...calculations for heat balance would be compromised.");
    2275           0 :                         SubSurfaceSevereDisplayed = true;
    2276             :                     }
    2277             :                     //        SurfError=.TRUE.
    2278             :                 }
    2279             :             }
    2280             :         }
    2281             : 
    2282             :         //**********************************************************************************
    2283             :         //   Set up Zone Surface Pointers
    2284        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2285        9632 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2286        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2287     1205945 :                 for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2288     1201128 :                     if (state.dataSurface->Surface(SurfNum).spaceNum == spaceNum) {
    2289       42219 :                         if (thisSpace.AllSurfaceFirst == 0) {
    2290        4818 :                             thisSpace.AllSurfaceFirst = SurfNum;
    2291             :                         }
    2292       42233 :                         if (state.dataSurface->Surface(SurfNum).IsAirBoundarySurf) {
    2293          14 :                             state.dataSurface->Surface(SurfNum).HeatTransSurf = false;
    2294          14 :                             continue;
    2295             :                         }
    2296       42205 :                         if (thisSpace.HTSurfaceFirst == 0) {
    2297        4818 :                             thisSpace.HTSurfaceFirst = SurfNum;
    2298             :                             // Non window surfaces are grouped next within each zone
    2299        4818 :                             thisSpace.OpaqOrIntMassSurfaceFirst = SurfNum;
    2300             :                         }
    2301       84426 :                         if ((thisSpace.WindowSurfaceFirst == 0) &&
    2302       75502 :                             ((state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) ||
    2303       72508 :                              (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
    2304       36232 :                              (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Diffuser))) {
    2305             :                             // Window surfaces are grouped last within each zone
    2306        2995 :                             thisSpace.WindowSurfaceFirst = SurfNum;
    2307        2995 :                             thisSpace.OpaqOrIntMassSurfaceLast = SurfNum - 1;
    2308             :                         }
    2309       42205 :                         if ((thisSpace.TDDDomeFirst == 0) && (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Dome)) {
    2310             :                             // Window surfaces are grouped last within each zone
    2311           1 :                             thisSpace.TDDDomeFirst = SurfNum;
    2312           1 :                             if (thisSpace.WindowSurfaceFirst != 0) {
    2313           0 :                                 thisSpace.WindowSurfaceLast = SurfNum - 1;
    2314             :                             } else {
    2315             :                                 // No window in the zone.
    2316           1 :                                 thisSpace.OpaqOrIntMassSurfaceLast = SurfNum - 1;
    2317           1 :                                 thisSpace.WindowSurfaceLast = -1;
    2318             :                             }
    2319           1 :                             break;
    2320             :                         }
    2321             :                     }
    2322             :                 }
    2323             :             }
    2324        4814 :             int firstSpaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
    2325        4814 :             state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst = state.dataHeatBal->space(firstSpaceNum).AllSurfaceFirst;
    2326             :         }
    2327             :         //  Surface First pointers are set, set last
    2328         771 :         if (state.dataGlobal->NumOfZones > 0) {
    2329         741 :             state.dataHeatBal->Zone(state.dataGlobal->NumOfZones).AllSurfaceLast = state.dataSurface->TotSurfaces;
    2330         741 :             int lastSpaceNum = state.dataHeatBal->Zone(state.dataGlobal->NumOfZones)
    2331         741 :                                    .spaceIndexes(state.dataHeatBal->Zone(state.dataGlobal->NumOfZones).spaceIndexes.size());
    2332         741 :             state.dataHeatBal->space(lastSpaceNum).AllSurfaceLast = state.dataSurface->TotSurfaces;
    2333             :         }
    2334        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2335        4814 :             if (ZoneNum < state.dataGlobal->NumOfZones) {
    2336        4073 :                 state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum + 1).AllSurfaceFirst - 1;
    2337             :             }
    2338        4814 :             auto &thisSpaceList = state.dataHeatBal->Zone(ZoneNum).spaceIndexes;
    2339        4814 :             int numSpacesInZone = thisSpaceList.size();
    2340        4814 :             if (numSpacesInZone > 1) {
    2341           6 :                 for (int spaceCount = 1; spaceCount <= numSpacesInZone - 1; ++spaceCount) {
    2342           4 :                     auto &thisSpace = state.dataHeatBal->space(thisSpaceList(spaceCount));
    2343           4 :                     auto &nextSpace = state.dataHeatBal->space(thisSpaceList(spaceCount + 1));
    2344           4 :                     thisSpace.AllSurfaceLast = nextSpace.AllSurfaceFirst - 1;
    2345             :                 }
    2346           2 :                 state.dataHeatBal->space(thisSpaceList(numSpacesInZone)).AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast;
    2347        4812 :             } else if (numSpacesInZone == 1) {
    2348        4812 :                 auto &thisSpace = state.dataHeatBal->space(thisSpaceList(numSpacesInZone));
    2349        4812 :                 thisSpace.AllSurfaceFirst = state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst;
    2350        4812 :                 thisSpace.AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast;
    2351             :             }
    2352             :         }
    2353        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2354        9632 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2355        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2356        4818 :                 if (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::TDD_Dome) {
    2357           1 :                     thisSpace.TDDDomeLast = thisSpace.AllSurfaceLast;
    2358       11907 :                 } else if ((state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::Window) ||
    2359        6640 :                            (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
    2360        1823 :                            (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::TDD_Diffuser)) {
    2361        2995 :                     thisSpace.TDDDomeLast = -1;
    2362        2995 :                     thisSpace.WindowSurfaceLast = thisSpace.AllSurfaceLast;
    2363             :                 } else {
    2364             :                     // If there are no windows in the zone, then set this to -1 so any for loops on WindowSurfaceFirst to WindowSurfaceLast
    2365             :                     // will not execute. Same for TDDDome and its indices
    2366        1822 :                     thisSpace.TDDDomeLast = -1;
    2367        1822 :                     thisSpace.WindowSurfaceLast = -1;
    2368        1822 :                     thisSpace.OpaqOrIntMassSurfaceLast = thisSpace.AllSurfaceLast;
    2369             :                 }
    2370        4818 :                 thisSpace.OpaqOrWinSurfaceFirst = thisSpace.HTSurfaceFirst;
    2371        4818 :                 thisSpace.OpaqOrWinSurfaceLast = std::max(thisSpace.OpaqOrIntMassSurfaceLast, thisSpace.WindowSurfaceLast);
    2372        4818 :                 thisSpace.HTSurfaceLast = thisSpace.AllSurfaceLast;
    2373             :             }
    2374             :         }
    2375             : 
    2376        5585 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2377        4814 :             int zoneSurfCount = 0;
    2378        9632 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2379        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2380        4818 :                 if (thisSpace.HTSurfaceFirst > 0) {
    2381        4818 :                     zoneSurfCount += (thisSpace.HTSurfaceLast - thisSpace.HTSurfaceFirst + 1);
    2382             :                 }
    2383        4818 :                 if (zoneSurfCount == 0) {
    2384           0 :                     ShowSevereError(state,
    2385           0 :                                     std::string{RoutineName} + "Zone has no heat transfer surfaces, Zone=" + state.dataHeatBal->Zone(ZoneNum).Name);
    2386           0 :                     SurfError = true;
    2387             :                 }
    2388             :             }
    2389             :         }
    2390             : 
    2391             :         // Set up Floor Areas for Zones and Spaces
    2392         771 :         Real64 constexpr floorAreaTolerance(0.05);
    2393         771 :         Real64 constexpr floorAreaPercentTolerance(floorAreaTolerance * 100.0);
    2394         771 :         if (!SurfError) {
    2395        5585 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2396        4814 :                 auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
    2397        9632 :                 for (int spaceNum : thisZone.spaceIndexes) {
    2398        4818 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2399       47024 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    2400       42206 :                         auto &thisSurf = state.dataSurface->Surface(SurfNum);
    2401       42206 :                         if (thisSurf.Class == SurfaceClass::Floor) {
    2402        6522 :                             thisZone.HasFloor = true;
    2403        6522 :                             state.dataHeatBal->space(spaceNum).calcFloorArea += thisSurf.Area;
    2404             :                         }
    2405       42206 :                         if (thisSurf.Class == SurfaceClass::Roof) {
    2406        5490 :                             thisZone.CeilingArea += thisSurf.Area;
    2407        5490 :                             thisZone.HasRoof = true;
    2408             :                         }
    2409             :                     }
    2410             :                 }
    2411             :             }
    2412         771 :             ErrCount = 0;
    2413        5589 :             for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
    2414        4818 :                 if (state.dataHeatBal->space(spaceNum).userEnteredFloorArea != DataGlobalConstants::AutoCalculate) {
    2415             :                     // Check entered vs calculated
    2416           0 :                     if (state.dataHeatBal->space(spaceNum).userEnteredFloorArea > 0.0) { // User entered Space floor area,
    2417             :                         // produce message if not near calculated
    2418           0 :                         if (state.dataHeatBal->space(spaceNum).calcFloorArea > 0.0) {
    2419             :                             Real64 diffp =
    2420           0 :                                 std::abs(state.dataHeatBal->space(spaceNum).calcFloorArea - state.dataHeatBal->space(spaceNum).userEnteredFloorArea) /
    2421           0 :                                 state.dataHeatBal->space(spaceNum).userEnteredFloorArea;
    2422           0 :                             if (diffp > floorAreaTolerance) {
    2423           0 :                                 ++ErrCount;
    2424           0 :                                 if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2425           0 :                                     ShowWarningError(
    2426             :                                         state,
    2427           0 :                                         format("{}Entered Space Floor Area(s) differ more than {:.0R}% from calculated Space Floor Area(s).",
    2428           0 :                                                std::string(RoutineName),
    2429           0 :                                                floorAreaPercentTolerance));
    2430           0 :                                     ShowContinueError(state,
    2431             :                                                       "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual Spaces.");
    2432             :                                 }
    2433           0 :                                 if (state.dataGlobal->DisplayExtraWarnings) {
    2434             :                                     // Warn user of using specified Space Floor Area
    2435           0 :                                     ShowWarningError(
    2436             :                                         state,
    2437           0 :                                         format("{}Entered Floor Area for Space=\"{}\" is {:.1R}% different from the calculated Floor Area.",
    2438           0 :                                                std::string(RoutineName),
    2439           0 :                                                state.dataHeatBal->space(spaceNum).Name,
    2440           0 :                                                diffp * 100.0));
    2441           0 :                                     ShowContinueError(state,
    2442           0 :                                                       format("Entered Space Floor Area={:.2R}, Calculated Space Floor Area={:.2R}, entered "
    2443             :                                                              "Floor Area will be used.",
    2444           0 :                                                              state.dataHeatBal->space(spaceNum).userEnteredFloorArea,
    2445           0 :                                                              state.dataHeatBal->space(spaceNum).calcFloorArea));
    2446             :                                 }
    2447             :                             }
    2448             :                         }
    2449           0 :                         state.dataHeatBal->space(spaceNum).floorArea = state.dataHeatBal->space(spaceNum).userEnteredFloorArea;
    2450           0 :                         state.dataHeatBal->space(spaceNum).hasFloor = true;
    2451             :                     }
    2452             :                 } else {
    2453        4818 :                     state.dataHeatBal->space(spaceNum).floorArea = state.dataHeatBal->space(spaceNum).calcFloorArea;
    2454             :                 }
    2455             :             }
    2456         771 :             ErrCount = 0;
    2457        5585 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2458             :                 // Calculate zone floor area as sum of space floor areas
    2459        9632 :                 for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2460        4818 :                     state.dataHeatBal->Zone(ZoneNum).CalcFloorArea += state.dataHeatBal->space(spaceNum).floorArea;
    2461             :                 }
    2462        4814 :                 if (state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea != DataGlobalConstants::AutoCalculate) {
    2463             :                     // Check entered vs calculated
    2464           4 :                     if (state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea > 0.0) { // User entered zone floor area,
    2465             :                         // produce message if not near calculated
    2466           4 :                         if (state.dataHeatBal->Zone(ZoneNum).CalcFloorArea > 0.0) {
    2467             :                             Real64 diffp =
    2468           4 :                                 std::abs(state.dataHeatBal->Zone(ZoneNum).CalcFloorArea - state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea) /
    2469           4 :                                 state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea;
    2470           4 :                             if (diffp > 0.05) {
    2471           1 :                                 ++ErrCount;
    2472           1 :                                 if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2473           3 :                                     ShowWarningError(
    2474             :                                         state,
    2475           2 :                                         format("{}Entered Zone Floor Area(s) differ more than {:.0R}% from the sum of the Space Floor Area(s).",
    2476           2 :                                                std::string(RoutineName),
    2477           1 :                                                floorAreaPercentTolerance));
    2478           1 :                                     ShowContinueError(state,
    2479             :                                                       "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
    2480             :                                 }
    2481           1 :                                 if (state.dataGlobal->DisplayExtraWarnings) {
    2482             :                                     // Warn user of using specified Zone Floor Area
    2483           0 :                                     ShowWarningError(state,
    2484           0 :                                                      format("{}Entered Floor Area for Zone=\"{}\" is {:.1R}% different from the sum of the "
    2485             :                                                             "Space Floor Area(s).",
    2486           0 :                                                             std::string(RoutineName),
    2487           0 :                                                             state.dataHeatBal->Zone(ZoneNum).Name,
    2488           0 :                                                             diffp * 100.0));
    2489           0 :                                     ShowContinueError(state,
    2490           0 :                                                       format("Entered Zone Floor Area={:.2R}, Sum of Space Floor Area(s)={:.2R}",
    2491           0 :                                                              state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea,
    2492           0 :                                                              state.dataHeatBal->Zone(ZoneNum).CalcFloorArea));
    2493           0 :                                     ShowContinueError(
    2494             :                                         state, "Entered Zone Floor Area will be used and Space Floor Area(s) will be adjusted proportionately.");
    2495             :                                 }
    2496             :                             }
    2497             :                         }
    2498           4 :                         state.dataHeatBal->Zone(ZoneNum).FloorArea = state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea;
    2499           4 :                         state.dataHeatBal->Zone(ZoneNum).HasFloor = true;
    2500             : 
    2501             :                         // Adjust space floor areas to match zone floor area
    2502           4 :                         if (state.dataHeatBal->Zone(ZoneNum).numSpaces == 1) {
    2503             :                             // If the zone contains only one space, then set the Space area to the Zone area
    2504           4 :                             int spaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
    2505           4 :                             state.dataHeatBal->space(spaceNum).floorArea = state.dataHeatBal->Zone(ZoneNum).FloorArea;
    2506           0 :                         } else if (state.dataHeatBal->Zone(ZoneNum).CalcFloorArea > 0.0) {
    2507             :                             // Adjust space areas proportionately
    2508           0 :                             Real64 areaRatio = state.dataHeatBal->Zone(ZoneNum).FloorArea / state.dataHeatBal->Zone(ZoneNum).CalcFloorArea;
    2509           0 :                             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2510           0 :                                 state.dataHeatBal->space(spaceNum).floorArea *= areaRatio;
    2511             :                             }
    2512             :                         } else {
    2513           0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    2514             :                                 // Warn if calculated floor area was zero and there is more than one Space
    2515           0 :                                 ShowWarningError(state,
    2516           0 :                                                  std::string{RoutineName} + "Entered Floor Area entered for Zone=\"" +
    2517           0 :                                                      state.dataHeatBal->Zone(ZoneNum).Name +
    2518             :                                                      "\" significantly different from sum of Space Floor Areas");
    2519           0 :                                 ShowContinueError(state,
    2520             :                                                   "But the sum of the Space Floor Areas is zero and there is more than one Space in the zone."
    2521             :                                                   "Unable to apportion the zone floor area. Space Floor Areas are zero.");
    2522             :                             }
    2523             :                         }
    2524             :                     } else {
    2525           0 :                         if (state.dataHeatBal->Zone(ZoneNum).CalcFloorArea > 0.0)
    2526           0 :                             state.dataHeatBal->Zone(ZoneNum).FloorArea = state.dataHeatBal->Zone(ZoneNum).CalcFloorArea;
    2527             :                     }
    2528             :                 } else {
    2529        4810 :                     state.dataHeatBal->Zone(ZoneNum).FloorArea = state.dataHeatBal->Zone(ZoneNum).CalcFloorArea;
    2530             :                 }
    2531        4814 :                 Real64 totSpacesFloorArea = 0.0;
    2532        9632 :                 for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2533        4818 :                     totSpacesFloorArea += state.dataHeatBal->space(spaceNum).floorArea;
    2534             :                 }
    2535        4814 :                 if (totSpacesFloorArea > 0.0) {
    2536        9628 :                     for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2537        4816 :                         state.dataHeatBal->space(spaceNum).fracZoneFloorArea = state.dataHeatBal->space(spaceNum).floorArea / totSpacesFloorArea;
    2538             :                     }
    2539             :                 } // else leave fractions at zero
    2540             :             }
    2541             :         }
    2542             : 
    2543       44533 :         for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2544       43762 :             if (state.dataSurface->Surface(SurfNum).Area < 1.e-06) {
    2545           0 :                 ShowSevereError(state,
    2546           0 :                                 format("{}Zero or negative surface area[{:.5R}], Surface={}",
    2547             :                                        RoutineName,
    2548           0 :                                        state.dataSurface->Surface(SurfNum).Area,
    2549           0 :                                        state.dataSurface->Surface(SurfNum).Name));
    2550           0 :                 SurfError = true;
    2551             :             }
    2552       43762 :             if (state.dataSurface->Surface(SurfNum).Area >= 1.e-06 && state.dataSurface->Surface(SurfNum).Area < 0.001) {
    2553           0 :                 ShowWarningError(state,
    2554           0 :                                  format("{}Very small surface area[{:.5R}], Surface={}",
    2555             :                                         RoutineName,
    2556           0 :                                         state.dataSurface->Surface(SurfNum).Area,
    2557           0 :                                         state.dataSurface->Surface(SurfNum).Name));
    2558             :             }
    2559             :         }
    2560             : 
    2561       44533 :         for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2562             :             // GLASSDOORs and TDD:DIFFUSERs will be treated as windows in the subsequent heat transfer and daylighting
    2563             :             // calculations. Reset class to 'Window' after saving the original designation in SurfaceWindow.
    2564             : 
    2565       43762 :             state.dataSurface->SurfWinOriginalClass(SurfNum) = state.dataSurface->Surface(SurfNum).Class;
    2566             : 
    2567       87017 :             if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::GlassDoor ||
    2568       43255 :                 state.dataSurface->Surface(SurfNum).Class == SurfaceClass::TDD_Diffuser)
    2569         509 :                 state.dataSurface->Surface(SurfNum).Class = SurfaceClass::Window;
    2570             : 
    2571       43762 :             if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::TDD_Dome) {
    2572             :                 // Reset the TDD:DOME subsurface to act as a base surface that can shade and be shaded
    2573             :                 // NOTE: This must be set early so that subsequent shading calculations are done correctly
    2574           2 :                 state.dataSurface->Surface(SurfNum).BaseSurf = SurfNum;
    2575             :             }
    2576             :         }
    2577             : 
    2578         771 :         errFlag = false;
    2579         771 :         if (!SurfError) {
    2580       44533 :             for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2581       43762 :                 if (state.dataSurface->Surface(SurfNum).HasShadeControl) {
    2582         143 :                     WinShadingControlPtr =
    2583         143 :                         state.dataSurface->Surface(SurfNum).activeWindowShadingControl; // use first item since others should be identical
    2584         143 :                     if (state.dataSurface->WindowShadingControl(WinShadingControlPtr).slatAngleControl != SlatAngleControl::Fixed) {
    2585           3 :                         state.dataSurface->SurfWinMovableSlats(SurfNum) = true;
    2586           3 :                         state.dataSurface->AnyMovableSlat = true;
    2587           3 :                         state.dataHeatBalSurf->SurfMovSlatsIndexList.push_back(SurfNum);
    2588             :                     }
    2589             : 
    2590         143 :                     ConstrNumSh = state.dataSurface->Surface(SurfNum).activeShadedConstruction;
    2591         143 :                     if (ConstrNumSh <= 0) continue;
    2592             : 
    2593         143 :                     WinShadingType ShadingType = state.dataSurface->WindowShadingControl(WinShadingControlPtr).ShadingType;
    2594             : 
    2595             :                     // only for blinds
    2596         143 :                     if (ANY_BLIND(ShadingType)) {
    2597             : 
    2598             :                         // TH 1/7/2010. CR 7930
    2599             :                         // The old code did not consider between-glass blind. Also there should not be two blinds - both interior and exterior
    2600             :                         // Use the new generic code (assuming only one blind) as follows
    2601          75 :                         for (iTmp1 = 1; iTmp1 <= state.dataConstruction->Construct(ConstrNumSh).TotLayers; ++iTmp1) {
    2602          75 :                             iTmp2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(iTmp1);
    2603          75 :                             if (state.dataMaterial->Material(iTmp2).Group == DataHeatBalance::MaterialGroup::WindowBlind) {
    2604          34 :                                 BlNum = state.dataMaterial->Material(iTmp2).BlindDataPtr;
    2605          34 :                                 state.dataSurface->SurfWinBlindNumber(SurfNum) = BlNum;
    2606             :                                 // TH 2/18/2010. CR 8010
    2607             :                                 // if it is a blind with movable slats, create one new blind and set it to VariableSlat if not done so yet.
    2608             :                                 //  the new blind is created only once, it can be shared by multiple windows though.
    2609          37 :                                 if (state.dataSurface->SurfWinMovableSlats(SurfNum) &&
    2610           3 :                                     state.dataHeatBal->Blind(BlNum).SlatAngleType != DataWindowEquivalentLayer::AngleType::Variable) {
    2611           3 :                                     errFlag = false;
    2612           3 :                                     AddVariableSlatBlind(state, BlNum, BlNumNew, errFlag);
    2613             :                                     // point to the new blind
    2614           3 :                                     state.dataMaterial->Material(iTmp2).BlindDataPtr = BlNumNew;
    2615             :                                     // window surface points to new blind
    2616           3 :                                     state.dataSurface->SurfWinBlindNumber(SurfNum) = BlNumNew;
    2617             :                                 }
    2618          34 :                                 break;
    2619             :                             }
    2620             :                         }
    2621             : 
    2622          34 :                         if (errFlag) {
    2623           0 :                             ErrorsFound = true;
    2624           0 :                             ShowContinueError(state,
    2625           0 :                                               "WindowShadingControl " + state.dataSurface->WindowShadingControl(WinShadingControlPtr).Name +
    2626             :                                                   " has errors, program will terminate.");
    2627             :                         }
    2628             :                     }
    2629             :                 } // End of surface loop
    2630             : 
    2631             :                 // final associate fenestration surfaces referenced in WindowShadingControl
    2632       43762 :                 FinalAssociateWindowShadingControlFenestration(state, ErrorsFound);
    2633       43762 :                 CheckWindowShadingControlSimilarForWindow(state, ErrorsFound);
    2634             :             }
    2635             : 
    2636             :             // Check for zones with not enough surfaces
    2637        5585 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2638        4814 :                 int OpaqueHTSurfs = 0;        // Number of floors, walls and roofs in a zone
    2639        4814 :                 int OpaqueHTSurfsWithWin = 0; // Number of floors, walls and roofs with windows in a zone
    2640        4814 :                 int InternalMassSurfs = 0;    // Number of internal mass surfaces in a zone
    2641        4814 :                 int priorBaseSurfNum = 0;
    2642             : 
    2643        9632 :                 for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2644        4818 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2645        4818 :                     if (thisSpace.HTSurfaceFirst == 0) continue; // Zone with no surfaces
    2646       47024 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    2647       42206 :                         auto &thisSurf = state.dataSurface->Surface(SurfNum);
    2648       42206 :                         if (thisSurf.Class == SurfaceClass::Floor || thisSurf.Class == SurfaceClass::Wall || thisSurf.Class == SurfaceClass::Roof)
    2649       33480 :                             ++OpaqueHTSurfs;
    2650       42206 :                         if (thisSurf.Class == SurfaceClass::IntMass) ++InternalMassSurfs;
    2651       42206 :                         if (thisSurf.Class == SurfaceClass::Window) {
    2652             :                             // Count base surface only once for multiple windows on a wall
    2653        5974 :                             int thisBaseSurfNum = thisSurf.BaseSurf;
    2654        5974 :                             if (thisBaseSurfNum != priorBaseSurfNum) {
    2655        3934 :                                 ++OpaqueHTSurfsWithWin;
    2656        3934 :                                 priorBaseSurfNum = thisBaseSurfNum;
    2657             :                             }
    2658             :                         }
    2659             :                     }
    2660             :                 }
    2661        4814 :                 if (OpaqueHTSurfsWithWin == 1 && OpaqueHTSurfs == 1 && InternalMassSurfs == 0) {
    2662           0 :                     SurfError = true;
    2663           0 :                     ShowSevereError(state,
    2664           0 :                                     std::string{RoutineName} + "Zone " + state.dataHeatBal->Zone(ZoneNum).Name +
    2665             :                                         " has only one floor, wall or roof, and this surface has a window.");
    2666           0 :                     ShowContinueError(state, "Add more floors, walls or roofs, or an internal mass surface.");
    2667             :                 }
    2668             :             }
    2669             : 
    2670             :             // set up vertex of centroid for each surface.
    2671         771 :             CalcSurfaceCentroid(state);
    2672             : 
    2673         771 :             SetupShadeSurfacesForSolarCalcs(state); // if shading surfaces are solar collectors or PV, then we need full solar calc.
    2674             : 
    2675         771 :             GetMovableInsulationData(state, ErrorsFound);
    2676             : 
    2677         771 :             if (state.dataSurface->CalcSolRefl) GetShadingSurfReflectanceData(state, ErrorsFound);
    2678             : 
    2679         771 :             LayNumOutside = 0;
    2680       44533 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2681             :                 // Check for EcoRoof and only 1 allowed to be used.
    2682       43762 :                 if (state.dataSurface->Surface(SurfNum).Construction > 0)
    2683       42220 :                     state.dataSurface->SurfExtEcoRoof(SurfNum) =
    2684       42220 :                         state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsEcoRoof;
    2685       43762 :                 if (!state.dataSurface->SurfExtEcoRoof(SurfNum)) continue;
    2686          24 :                 if (LayNumOutside == 0) {
    2687           4 :                     LayNumOutside = state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).LayerPoint(1);
    2688           4 :                     continue;
    2689             :                 }
    2690          16 :                 if (LayNumOutside != state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).LayerPoint(1)) {
    2691           0 :                     ShowSevereError(state, std::string{RoutineName} + "Only one EcoRoof Material is currently allowed for all constructions.");
    2692           0 :                     ShowContinueError(state, "... first material=" + state.dataMaterial->Material(LayNumOutside).Name);
    2693           0 :                     ShowContinueError(
    2694             :                         state,
    2695           0 :                         "... conflicting Construction=" + state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).Name +
    2696           0 :                             " uses material=" +
    2697             :                             state.dataMaterial
    2698           0 :                                 ->Material(state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).LayerPoint(1))
    2699             :                                 .Name);
    2700           0 :                     ErrorsFound = true;
    2701             :                 }
    2702             :             }
    2703             : 
    2704             :             // Reserve space to avoid excess allocations
    2705         771 :             state.dataSurface->AllHTSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2706         771 :             state.dataSurface->AllExtSolarSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2707         771 :             state.dataSurface->AllShadowPossObstrSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2708         771 :             state.dataSurface->AllIZSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2709         771 :             state.dataSurface->AllHTNonWindowSurfaceList.reserve(state.dataSurface->TotSurfaces - state.dataSurface->TotWindows);
    2710         771 :             state.dataSurface->AllHTWindowSurfaceList.reserve(state.dataSurface->TotWindows);
    2711         771 :             state.dataSurface->AllExtSolWindowSurfaceList.reserve(state.dataSurface->TotWindows);
    2712         771 :             state.dataSurface->AllExtSolWinWithFrameSurfaceList.reserve(state.dataSurface->TotWindows);
    2713         771 :             state.dataSurface->AllHTKivaSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2714             : 
    2715             :             // Set flag that determines whether a surface can be an exterior obstruction
    2716             :             // Also set associated surfaces for Kiva foundations and build heat transfer surface lists
    2717       44533 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2718       43762 :                 state.dataSurface->Surface(SurfNum).IsShadowPossibleObstruction = false;
    2719       43762 :                 if (state.dataSurface->Surface(SurfNum).ExtSolar) {
    2720             :                     // This may include some attached shading surfaces
    2721       18381 :                     state.dataSurface->AllExtSolarSurfaceList.push_back(SurfNum);
    2722             :                 }
    2723       43762 :                 if (state.dataSurface->Surface(SurfNum).HeatTransSurf) {
    2724             :                     // Outside light shelves get tagged later as HeatTransSurf=true but they haven't been processed yet
    2725       42206 :                     state.dataSurface->AllHTSurfaceList.push_back(SurfNum);
    2726       42206 :                     int const zoneNum(state.dataSurface->Surface(SurfNum).Zone);
    2727       42206 :                     auto &surfZone(state.dataHeatBal->Zone(zoneNum));
    2728       42206 :                     surfZone.ZoneHTSurfaceList.push_back(SurfNum);
    2729             :                     // Sort window vs non-window surfaces
    2730       42206 :                     if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
    2731        5974 :                         state.dataSurface->AllHTWindowSurfaceList.push_back(SurfNum);
    2732        5974 :                         surfZone.ZoneHTWindowSurfaceList.push_back(SurfNum);
    2733        5974 :                         if (state.dataSurface->Surface(SurfNum).ExtSolar) {
    2734        5958 :                             state.dataSurface->AllExtSolWindowSurfaceList.push_back(SurfNum);
    2735        5958 :                             if (state.dataSurface->Surface(SurfNum).FrameDivider > 0) {
    2736         381 :                                 state.dataSurface->AllExtSolWinWithFrameSurfaceList.push_back(SurfNum);
    2737             :                             }
    2738             :                         }
    2739             :                     } else {
    2740       36232 :                         state.dataSurface->AllHTNonWindowSurfaceList.push_back(SurfNum);
    2741       36232 :                         surfZone.ZoneHTNonWindowSurfaceList.push_back(SurfNum);
    2742             :                     }
    2743       42206 :                     int const surfExtBoundCond(state.dataSurface->Surface(SurfNum).ExtBoundCond);
    2744             :                     // Build zone and interzone surface lists
    2745       42206 :                     if ((surfExtBoundCond > 0) && (surfExtBoundCond != SurfNum)) {
    2746       16844 :                         state.dataSurface->AllIZSurfaceList.push_back(SurfNum);
    2747       16844 :                         surfZone.ZoneIZSurfaceList.push_back(SurfNum);
    2748       16844 :                         auto &adjZone(state.dataHeatBal->Zone(state.dataSurface->Surface(surfExtBoundCond).Zone));
    2749       16844 :                         adjZone.ZoneHTSurfaceList.push_back(SurfNum);
    2750       16844 :                         adjZone.ZoneIZSurfaceList.push_back(SurfNum);
    2751             :                         // Sort window vs non-window surfaces
    2752       16844 :                         if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
    2753          14 :                             adjZone.ZoneHTWindowSurfaceList.push_back(SurfNum);
    2754             :                         } else {
    2755       16830 :                             adjZone.ZoneHTNonWindowSurfaceList.push_back(SurfNum);
    2756             :                         }
    2757             :                     }
    2758             :                 }
    2759             :                 // Exclude non-exterior heat transfer surfaces (but not OtherSideCondModeledExt = -4 CR7640)
    2760       43762 :                 if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue;
    2761       21044 :                 if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == Ground) continue;
    2762       18965 :                 if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == KivaFoundation) {
    2763          38 :                     state.dataSurface->AllHTKivaSurfaceList.push_back(SurfNum);
    2764          38 :                     if (!ErrorsFound)
    2765          38 :                         state.dataSurfaceGeometry->kivaManager.foundationInputs[state.dataSurface->Surface(SurfNum).OSCPtr].surfaces.push_back(
    2766             :                             SurfNum);
    2767          38 :                     continue;
    2768             :                 }
    2769       18889 :                 if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt)
    2770          32 :                     continue;
    2771       18857 :                 if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == OtherSideCoefCalcExt)
    2772           1 :                     continue;
    2773             :                 // Exclude windows and doors, i.e., consider only their base surfaces as possible obstructions
    2774       31752 :                 if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window ||
    2775       12896 :                     state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Door)
    2776        6345 :                     continue;
    2777             :                 // Exclude duplicate shading surfaces
    2778       12511 :                 if (state.dataSurface->Surface(SurfNum).MirroredSurf) continue;
    2779             :                 // Exclude air boundary surfaces
    2780       11740 :                 if (state.dataSurface->Surface(SurfNum).IsAirBoundarySurf) continue;
    2781             : 
    2782       11726 :                 state.dataSurface->Surface(SurfNum).IsShadowPossibleObstruction = true;
    2783       11726 :                 state.dataSurface->AllShadowPossObstrSurfaceList.push_back(SurfNum);
    2784             :             }
    2785             : 
    2786             :             // Check for IRT surfaces in invalid places.
    2787         771 :             iTmp1 = 0;
    2788         771 :             if (std::any_of(state.dataConstruction->Construct.begin(),
    2789         771 :                             state.dataConstruction->Construct.end(),
    2790        5843 :                             [](Construction::ConstructionProps const &e) { return e.TypeIsIRT; })) {
    2791          76 :                 for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2792          74 :                     if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue; // ignore shading surfaces
    2793          74 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum)
    2794          28 :                         continue; // interzone, not adiabatic surface
    2795          46 :                     if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsIRT) {
    2796          46 :                         continue;
    2797             :                     }
    2798           0 :                     if (!state.dataGlobal->DisplayExtraWarnings) {
    2799           0 :                         ++iTmp1;
    2800             :                     } else {
    2801           0 :                         ShowWarningError(state,
    2802           0 :                                          std::string{RoutineName} + "Surface=\"" + state.dataSurface->Surface(SurfNum).Name +
    2803             :                                              "\" uses InfraredTransparent construction in a non-interzone surface. (illegal use)");
    2804             :                     }
    2805             :                 }
    2806           2 :                 if (iTmp1 > 0) {
    2807           0 :                     ShowWarningError(
    2808             :                         state,
    2809           0 :                         format("{}Surfaces use InfraredTransparent constructions {} in non-interzone surfaces. (illegal use)", RoutineName, iTmp1));
    2810           0 :                     ShowContinueError(state, "For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;");
    2811             :                 }
    2812             :             }
    2813             : 
    2814             :             // Note, could do same for Window Area and detecting if Interzone Surface in Zone
    2815             : 
    2816         771 :             if (state.dataSurfaceGeometry->Warning1Count > 0) {
    2817          15 :                 ShowWarningMessage(state,
    2818          15 :                                    format("{}Window dimensions differ from Window 5/6 data file dimensions, {} times.",
    2819             :                                           RoutineName,
    2820          10 :                                           state.dataSurfaceGeometry->Warning1Count));
    2821           5 :                 ShowContinueError(state, "This will affect the frame heat transfer calculation if the frame in the Data File entry");
    2822           5 :                 ShowContinueError(state, "is not uniform, i.e., has sections with different geometry and/or thermal properties.");
    2823           5 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2824             :             }
    2825         771 :             if (state.dataSurfaceGeometry->Warning2Count > 0) {
    2826           0 :                 ShowWarningMessage(state,
    2827           0 :                                    format("{}Exterior Windows have been replaced with Window 5/6 two glazing systems, {} times.",
    2828             :                                           RoutineName,
    2829           0 :                                           state.dataSurfaceGeometry->Warning2Count));
    2830           0 :                 ShowContinueError(state, "Note that originally entered dimensions are overridden.");
    2831           0 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2832             :             }
    2833         771 :             if (state.dataSurfaceGeometry->Warning3Count > 0) {
    2834           0 :                 ShowWarningMessage(state,
    2835           0 :                                    format("{}Interior Windows have been replaced with Window 5/6 two glazing systems, {} times.",
    2836             :                                           RoutineName,
    2837           0 :                                           state.dataSurfaceGeometry->Warning3Count));
    2838           0 :                 ShowContinueError(state, "Note that originally entered dimensions are overridden.");
    2839           0 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2840             :             }
    2841             : 
    2842         771 :             if (state.dataErrTracking->TotalMultipliedWindows > 0) {
    2843           3 :                 ShowWarningMessage(state,
    2844           3 :                                    format("{}There are {} window/glass door(s) that may cause inaccurate shadowing due to Solar Distribution.",
    2845             :                                           RoutineName,
    2846           2 :                                           state.dataErrTracking->TotalMultipliedWindows));
    2847           1 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2848           1 :                 state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalMultipliedWindows;
    2849             :             }
    2850         771 :             if (state.dataErrTracking->TotalCoincidentVertices > 0) {
    2851           0 :                 ShowWarningMessage(state,
    2852           0 :                                    format("{}There are {} coincident/collinear vertices; These have been deleted unless the deletion would bring the "
    2853             :                                           "number of surface sides < 3.",
    2854             :                                           RoutineName,
    2855           0 :                                           state.dataErrTracking->TotalCoincidentVertices));
    2856           0 :                 ShowContinueError(state, "For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;");
    2857           0 :                 state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalCoincidentVertices;
    2858             :             }
    2859         771 :             if (state.dataErrTracking->TotalDegenerateSurfaces > 0) {
    2860           0 :                 ShowSevereMessage(state,
    2861           0 :                                   format("{}There are {} degenerate surfaces; Degenerate surfaces are those with number of sides < 3.",
    2862             :                                          RoutineName,
    2863           0 :                                          state.dataErrTracking->TotalDegenerateSurfaces));
    2864           0 :                 ShowContinueError(state, "These surfaces should be deleted.");
    2865           0 :                 ShowContinueError(state, "For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;");
    2866           0 :                 state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalDegenerateSurfaces;
    2867             :             }
    2868             : 
    2869         771 :             GetHTSurfExtVentedCavityData(state, ErrorsFound);
    2870             : 
    2871         771 :             state.dataSurfaceGeometry->exposedFoundationPerimeter.getData(state, ErrorsFound);
    2872             : 
    2873         771 :             GetSurfaceHeatTransferAlgorithmOverrides(state, ErrorsFound);
    2874             : 
    2875             :             // Set up enclosures, process Air Boundaries if any
    2876         771 :             SetupEnclosuresAndAirBoundaries(state, state.dataViewFactor->EnclRadInfo, SurfaceGeometry::enclosureType::RadiantEnclosures, ErrorsFound);
    2877             : 
    2878         771 :             GetSurfaceGroundSurfsData(state, ErrorsFound);
    2879             : 
    2880         771 :             GetSurfaceSrdSurfsData(state, ErrorsFound);
    2881             : 
    2882         771 :             GetSurfaceLocalEnvData(state, ErrorsFound);
    2883             : 
    2884         771 :             if (SurfError || ErrorsFound) {
    2885           0 :                 ErrorsFound = true;
    2886           0 :                 ShowFatalError(state, std::string{RoutineName} + "Errors discovered, program terminates.");
    2887             :             }
    2888             : 
    2889        1542 :             int TotShadSurf = TotDetachedFixed + TotDetachedBldg + TotRectDetachedFixed + TotRectDetachedBldg + TotShdSubs + TotOverhangs +
    2890         771 :                               TotOverhangsProjection + TotFins + TotFinsProjection;
    2891         771 :             int NumDElightCmplxFen = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Daylighting:DElight:ComplexFenestration");
    2892         771 :             if (TotShadSurf > 0 && (NumDElightCmplxFen > 0 || DaylightingManager::doesDayLightingUseDElight(state))) {
    2893           0 :                 ShowWarningError(state,
    2894           0 :                                  std::string{RoutineName} + "When using DElight daylighting the presence of exterior shading surfaces is ignored.");
    2895             :             }
    2896             : 
    2897       44533 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
    2898             :                 // Initialize run time surface arrays
    2899       43762 :                 state.dataSurface->SurfActiveConstruction(SurfNum) = state.dataSurface->Surface(SurfNum).Construction;
    2900       43762 :                 state.dataSurface->Surface(SurfNum).RepresentativeCalcSurfNum = SurfNum;
    2901             :             }
    2902             : 
    2903             :             // Representative surface calculations: Assign representative heat transfer surfaces
    2904        1543 :             if (state.dataSurface->UseRepresentativeSurfaceCalculations &&
    2905         772 :                 state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneProperty:UserViewFactors:BySurfaceName") == 0) {
    2906          47 :                 for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2907          92 :                     for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2908          46 :                         auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2909         625 :                         for (int surfNum = thisSpace.HTSurfaceFirst; surfNum <= thisSpace.HTSurfaceLast; surfNum++) {
    2910         579 :                             auto &surface(state.dataSurface->Surface(surfNum));
    2911             :                             // Conditions where surface always needs to be unique
    2912             :                             bool forceUniqueSurface =
    2913        1158 :                                 surface.HasShadeControl ||
    2914        1158 :                                 state.dataSurface->SurfWinAirflowSource(surfNum) != DataSurfaces::WindowAirFlowSource::Invalid ||
    2915        1158 :                                 state.dataConstruction->Construct(surface.Construction).SourceSinkPresent ||
    2916        1737 :                                 surface.Class == SurfaceClass::TDD_Dome ||
    2917         757 :                                 (surface.Class == SurfaceClass::Window &&
    2918         356 :                                  (state.dataSurface->SurfWinOriginalClass(surfNum) == SurfaceClass::TDD_Diffuser ||
    2919         356 :                                   state.dataSurface->SurfWinWindowModelType(surfNum) != WindowModel::Detailed ||
    2920         356 :                                   state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() ||
    2921         757 :                                   state.dataConstruction->Construct(surface.Construction).TCFlag == 1));
    2922         579 :                             if (!forceUniqueSurface) {
    2923         579 :                                 state.dataSurface->Surface(surfNum).set_representative_surface(state, surfNum);
    2924             :                             }
    2925             :                         }
    2926             :                     }
    2927             :                 }
    2928             :             }
    2929             :             // Initialize surface with movable insulation index list
    2930       44533 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
    2931       43762 :                 if (state.dataSurface->SurfMaterialMovInsulExt(SurfNum) > 0 || state.dataSurface->SurfMaterialMovInsulInt(SurfNum) > 0) {
    2932           5 :                     state.dataHeatBalSurf->SurfMovInsulIndexList.push_back(SurfNum);
    2933             :                 }
    2934             :             }
    2935             :         }
    2936             :     }
    2937             : 
    2938         771 :     void CreateMissingSpaces(EnergyPlusData &state, Array1D<SurfaceGeometry::SurfaceData> &Surfaces)
    2939             :     {
    2940             :         // Scan surfaces to see if Space was assigned in input
    2941       44533 :         for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
    2942       43762 :             auto &thisSurf = Surfaces(surfNum);
    2943       43762 :             if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
    2944       42220 :             if (thisSurf.BaseSurf != surfNum) {
    2945             :                 // Set space for subsurfaces
    2946        6442 :                 thisSurf.spaceNum = Surfaces(thisSurf.BaseSurf).spaceNum;
    2947             :             }
    2948       42220 :             if (thisSurf.spaceNum > 0) {
    2949          27 :                 state.dataHeatBal->Zone(thisSurf.Zone).anySurfacesWithSpace = true;
    2950             :             } else {
    2951       42193 :                 state.dataHeatBal->Zone(thisSurf.Zone).anySurfacesWithoutSpace = true;
    2952             :             }
    2953             :         }
    2954             : 
    2955             :         // Create any missing Spaces
    2956        5585 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2957        4814 :             auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    2958        4814 :             if (thisZone.anySurfacesWithoutSpace) {
    2959             :                 // If any surfaces in the zone are not assigned to a space, may need to create a new space
    2960             :                 // Every zone has at least one space, created in HeatBalanceManager::GetSpaceData
    2961             :                 // If no surfaces have a space assigned, then the default space will be used, otherwise, create a new space
    2962        4812 :                 if (thisZone.anySurfacesWithSpace) {
    2963             :                     // Add new space
    2964           1 :                     ++state.dataGlobal->numSpaces;
    2965           1 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).zoneNum = zoneNum;
    2966             :                     // Add to zone's list of spaces
    2967           1 :                     thisZone.spaceIndexes.emplace_back(state.dataGlobal->numSpaces);
    2968           1 :                     ++state.dataHeatBal->Zone(zoneNum).numSpaces;
    2969           1 :                     assert(state.dataHeatBal->Zone(zoneNum).numSpaces == int(state.dataHeatBal->Zone(zoneNum).spaceIndexes.size()));
    2970             :                     // If some surfaces in the zone are assigned to a space, the new space is the remainder of the zone
    2971           1 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).Name = thisZone.Name + "-Remainder";
    2972           1 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).isRemainderSpace = true;
    2973           1 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceType = "GENERAL";
    2974           1 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceTypeNum = HeatBalanceManager::GetGeneralSpaceTypeNum(state);
    2975             :                 }
    2976             :             }
    2977             :         }
    2978             : 
    2979             :         // Assign Spaces to surfaces without one
    2980       44533 :         for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
    2981       43762 :             auto &thisSurf = Surfaces(surfNum);
    2982       43762 :             if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
    2983       42220 :             if (thisSurf.spaceNum == 0) {
    2984       42193 :                 int const numSpaces = state.dataHeatBal->Zone(thisSurf.Zone).numSpaces;
    2985       42193 :                 int const lastSpaceForZone = state.dataHeatBal->Zone(thisSurf.Zone).spaceIndexes(numSpaces);
    2986       42193 :                 thisSurf.spaceNum = lastSpaceForZone;
    2987             :             }
    2988             :         }
    2989         771 :     }
    2990             : 
    2991         771 :     void createSpaceSurfaceLists(EnergyPlusData &state, bool &ErrorsFound)
    2992             :     {
    2993             :         static constexpr std::string_view RoutineName("createSpaceSurfaceLists: ");
    2994             :         // Build Space surface lists now that all of the surface sorting is complete
    2995       44533 :         for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
    2996       43762 :             auto &thisSurf = state.dataSurface->Surface(surfNum);
    2997       43762 :             if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
    2998             :             // Add to Space's list of surfaces
    2999       42220 :             state.dataHeatBal->space(thisSurf.spaceNum).surfaces.emplace_back(surfNum);
    3000             :         }
    3001             :         // TODO MJW: Is this necessary? Check that all Spaces have at least one Surface
    3002        4848 :         for (int spaceNum = 1; spaceNum < state.dataGlobal->numSpaces; ++spaceNum) {
    3003        4077 :             if (int(state.dataHeatBal->space(spaceNum).surfaces.size()) == 0) {
    3004           0 :                 ShowSevereError(state, std::string(RoutineName) + "Space = " + state.dataHeatBal->space(spaceNum).Name + " has no surfaces.");
    3005           0 :                 ErrorsFound = true;
    3006             :             }
    3007             :         }
    3008         771 :     }
    3009        6442 :     void checkSubSurfAzTiltNorm(EnergyPlusData &state,
    3010             :                                 SurfaceData &baseSurface, // Base surface data (in)
    3011             :                                 SurfaceData &subSurface,  // Subsurface data (in)
    3012             :                                 bool &surfaceError        // True if surface azimuths or tilts differ by more than error tolerance
    3013             :     )
    3014             :     {
    3015        6442 :         bool sameSurfNormal(false); // True if surface has the same surface normal within tolerance
    3016        6442 :         bool baseSurfHoriz(false);  // True if base surface is near horizontal
    3017        6442 :         Real64 constexpr warningTolerance(30.0);
    3018        6442 :         Real64 constexpr errorTolerance(90.0);
    3019             : 
    3020        6442 :         surfaceError = false;
    3021             : 
    3022             :         // Check if base surface and subsurface have the same normal
    3023        6442 :         Vectors::CompareTwoVectors(baseSurface.NewellSurfaceNormalVector, subSurface.NewellSurfaceNormalVector, sameSurfNormal, 0.001);
    3024        6442 :         if (sameSurfNormal) { // copy lcs vectors
    3025             :             // Prior logic tested for azimuth difference < 30 and then skipped this - this caused large diffs in
    3026             :             // CmplxGlz_MeasuredDeflectionAndShading Restoring that check here but will require further investigation (MJW Dec 2015)
    3027        6441 :             if (std::abs(baseSurface.Azimuth - subSurface.Azimuth) > warningTolerance) {
    3028          60 :                 subSurface.lcsx = baseSurface.lcsx;
    3029          60 :                 subSurface.lcsy = baseSurface.lcsy;
    3030          60 :                 subSurface.lcsy = baseSurface.lcsy;
    3031             :             }
    3032             :         } else {
    3033             :             // Not sure what this does, but keeping for now (MJW Dec 2015)
    3034           1 :             if (std::abs(subSurface.Azimuth - 360.0) < 0.01) {
    3035           0 :                 subSurface.Azimuth = 360.0 - subSurface.Azimuth;
    3036             :             }
    3037           1 :             if (std::abs(baseSurface.Azimuth - 360.0) < 0.01) {
    3038           0 :                 baseSurface.Azimuth = 360.0 - baseSurface.Azimuth;
    3039             :             }
    3040             : 
    3041             :             // Is base surface horizontal? If so, ignore azimuth differences
    3042           1 :             if (std::abs(baseSurface.Tilt) <= 1.0e-5 || std::abs(baseSurface.Tilt - 180.0) <= 1.0e-5) baseSurfHoriz = true;
    3043             : 
    3044           2 :             if (((std::abs(baseSurface.Azimuth - subSurface.Azimuth) > errorTolerance) && !baseSurfHoriz) ||
    3045           1 :                 (std::abs(baseSurface.Tilt - subSurface.Tilt) > errorTolerance)) {
    3046           0 :                 surfaceError = true;
    3047           0 :                 ShowSevereError(
    3048             :                     state,
    3049           0 :                     format("checkSubSurfAzTiltNorm: Outward facing angle of subsurface differs more than {:.1R} degrees from base surface.",
    3050           0 :                            errorTolerance));
    3051           0 :                 ShowContinueError(state,
    3052           0 :                                   format("Subsurface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", subSurface.Name, subSurface.Tilt, subSurface.Azimuth));
    3053           0 :                 ShowContinueError(
    3054           0 :                     state, format("Base surface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", baseSurface.Name, baseSurface.Tilt, baseSurface.Azimuth));
    3055           2 :             } else if (((std::abs(baseSurface.Azimuth - subSurface.Azimuth) > warningTolerance) && !baseSurfHoriz) ||
    3056           1 :                        (std::abs(baseSurface.Tilt - subSurface.Tilt) > warningTolerance)) {
    3057           0 :                 ++state.dataSurfaceGeometry->checkSubSurfAzTiltNormErrCount;
    3058           0 :                 if (state.dataSurfaceGeometry->checkSubSurfAzTiltNormErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    3059           0 :                     ShowWarningError(state,
    3060           0 :                                      format("checkSubSurfAzTiltNorm: Some Outward Facing angles of subsurfaces differ more than {:.1R} "
    3061             :                                             "degrees from base surface.",
    3062           0 :                                             warningTolerance));
    3063           0 :                     ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
    3064             :                 }
    3065           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
    3066           0 :                     ShowWarningError(
    3067             :                         state,
    3068           0 :                         format("checkSubSurfAzTiltNorm: Outward facing angle of subsurface differs more than {:.1R} degrees from base surface.",
    3069           0 :                                warningTolerance));
    3070           0 :                     ShowContinueError(
    3071           0 :                         state, format("Subsurface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", subSurface.Name, subSurface.Tilt, subSurface.Azimuth));
    3072           0 :                     ShowContinueError(
    3073             :                         state,
    3074           0 :                         format("Base surface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", baseSurface.Name, baseSurface.Tilt, baseSurface.Azimuth));
    3075             :                 }
    3076             :             }
    3077             :         }
    3078        6442 :     }
    3079             : 
    3080         771 :     void GetGeometryParameters(EnergyPlusData &state, bool &ErrorsFound) // set to true if errors found during input
    3081             :     {
    3082             : 
    3083             :         // SUBROUTINE INFORMATION:
    3084             :         //       AUTHOR         Linda Lawrie
    3085             :         //       DATE WRITTEN   May 2000
    3086             :         //       MODIFIED       na
    3087             :         //       RE-ENGINEERED  na
    3088             : 
    3089             :         // PURPOSE OF THIS SUBROUTINE:
    3090             :         // This subroutine reads in the "Surface Geometry" parameters, verifies them,
    3091             :         // and sets "global" variables that will tell other routines how the surface
    3092             :         // vertices are expected in input.
    3093             : 
    3094             :         // METHODOLOGY EMPLOYED:
    3095             :         // na
    3096             : 
    3097             :         // REFERENCES:
    3098             :         // GlobalGeometryRules Definition
    3099             :         // GlobalGeometryRules,
    3100             :         //      \required-object
    3101             :         //      \unique-object
    3102             :         //  A1, \field Starting Vertex Position
    3103             :         //      \required-field
    3104             :         //      \note Specified as entry for a 4 sided surface/rectangle
    3105             :         //      \note Surfaces are specified as viewed from outside the surface
    3106             :         //      \note Shading surfaces as viewed from behind.  (towards what they are shading)
    3107             :         //      \type choice
    3108             :         //      \key UpperLeftCorner
    3109             :         //      \key LowerLeftCorner
    3110             :         //      \key UpperRightCorner
    3111             :         //      \key LowerRightCorner
    3112             :         //  A2, \field Vertex Entry Direction
    3113             :         //      \required-field
    3114             :         //      \type choice
    3115             :         //      \key Counterclockwise
    3116             :         //      \key Clockwise
    3117             :         //  A3, \field Coordinate System
    3118             :         //      \required-field
    3119             :         //      \note relative -- coordinates are entered relative to zone origin
    3120             :         //      \note world -- all coordinates entered are "absolute" for this facility
    3121             :         //      \note absolute -- same as world
    3122             :         //      \type choice
    3123             :         //      \key Relative
    3124             :         //      \key World
    3125             :         //      \key Absolute
    3126             :         //  A4, \field Daylighting Reference Point Coordinate System
    3127             :         //      \type choice
    3128             :         //      \key Relative
    3129             :         //      \default Relative
    3130             :         //      \note Relative -- coordinates are entered relative to zone origin
    3131             :         //      \key World
    3132             :         //      \note World -- all coordinates entered are "absolute" for this facility
    3133             :         //      \key Absolute
    3134             :         //      \note absolute -- same as world
    3135             :         //  A5; \field Rectangular Surface Coordinate System
    3136             :         //      \type choice
    3137             :         //      \key Relative
    3138             :         //      \default Relative
    3139             :         //      \note Relative -- Starting corner is entered relative to zone origin
    3140             :         //      \key World
    3141             :         //      \note World -- Starting corner is entered in "absolute"
    3142             :         //      \key Absolute
    3143             :         //      \note absolute -- same as world
    3144             : 
    3145             :         // Using/Aliasing
    3146             : 
    3147             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3148         771 :         static Array1D_string const FlCorners(4, {"UpperLeftCorner", "LowerLeftCorner", "LowerRightCorner", "UpperRightCorner"});
    3149             : 
    3150             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3151             :         int NumStmt;
    3152        1542 :         Array1D_string GAlphas(5);
    3153             :         int NAlphas;
    3154        1542 :         Array1D<Real64> GNum(1);
    3155             :         int NNum;
    3156             :         int IOStat;
    3157             :         bool OK;
    3158             :         int Found;
    3159        1542 :         std::string OutMsg;
    3160             :         int ZoneNum; // For loop counter
    3161         771 :         bool RelWarning(false);
    3162         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3163             : 
    3164         771 :         cCurrentModuleObject = "GlobalGeometryRules";
    3165         771 :         NumStmt = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    3166         771 :         OutMsg = " Surface Geometry,";
    3167             : 
    3168             :         {
    3169         771 :             auto const SELECT_CASE_var(NumStmt);
    3170             : 
    3171         771 :             if (SELECT_CASE_var == 1) {
    3172             :                 // This is the valid case
    3173        3855 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3174             :                                                                          cCurrentModuleObject,
    3175             :                                                                          1,
    3176             :                                                                          GAlphas,
    3177             :                                                                          NAlphas,
    3178             :                                                                          GNum,
    3179             :                                                                          NNum,
    3180             :                                                                          IOStat,
    3181         771 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3182         771 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3183         771 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3184         771 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3185             : 
    3186             :                 // Even though these will be validated, set defaults in case error here -- wont
    3187             :                 // cause aborts in later surface gets (hopefully)
    3188         771 :                 state.dataSurface->Corner = UpperLeftCorner;
    3189         771 :                 state.dataSurface->WorldCoordSystem = true;
    3190         771 :                 state.dataSurface->CCW = true;
    3191             : 
    3192         771 :                 OK = false;
    3193         771 :                 Found = UtilityRoutines::FindItem(GAlphas(1), FlCorners, 4);
    3194         771 :                 if (Found == 0) {
    3195           0 :                     ShowSevereError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' + GAlphas(1));
    3196           0 :                     ErrorsFound = true;
    3197             :                 } else {
    3198         771 :                     state.dataSurface->Corner = Found;
    3199         771 :                     OK = true;
    3200         771 :                     OutMsg += FlCorners(state.dataSurface->Corner) + ',';
    3201             :                 }
    3202             : 
    3203         771 :                 OK = false;
    3204         771 :                 if (UtilityRoutines::SameString(GAlphas(2), "CCW") || UtilityRoutines::SameString(GAlphas(2), "Counterclockwise")) {
    3205         768 :                     state.dataSurface->CCW = true;
    3206         768 :                     OutMsg += "Counterclockwise,";
    3207         768 :                     OK = true;
    3208             :                 }
    3209         771 :                 if (UtilityRoutines::SameString(GAlphas(2), "CW") || UtilityRoutines::SameString(GAlphas(2), "Clockwise")) {
    3210           3 :                     state.dataSurface->CCW = false;
    3211           3 :                     OutMsg += "Clockwise,";
    3212           3 :                     OK = true;
    3213             :                 }
    3214         771 :                 if (!OK) {
    3215           0 :                     ShowSevereError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + GAlphas(2));
    3216           0 :                     ErrorsFound = true;
    3217             :                 }
    3218             : 
    3219         771 :                 OK = false;
    3220         771 :                 if (UtilityRoutines::SameString(GAlphas(3), "World") || UtilityRoutines::SameString(GAlphas(3), "Absolute")) {
    3221         351 :                     state.dataSurface->WorldCoordSystem = true;
    3222         351 :                     OutMsg += "WorldCoordinateSystem,";
    3223         351 :                     OK = true;
    3224             :                 }
    3225         771 :                 if (UtilityRoutines::SameString(GAlphas(3), "Relative")) {
    3226         420 :                     state.dataSurface->WorldCoordSystem = false;
    3227         420 :                     OutMsg += "RelativeCoordinateSystem,";
    3228         420 :                     OK = true;
    3229             :                 }
    3230         771 :                 if (!OK) {
    3231           0 :                     ShowWarningError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + '=' + GAlphas(3));
    3232           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + " defaults to \"WorldCoordinateSystem\"");
    3233           0 :                     state.dataSurface->WorldCoordSystem = true;
    3234           0 :                     OutMsg += "WorldCoordinateSystem,";
    3235             :                 }
    3236             : 
    3237         771 :                 OK = false;
    3238         771 :                 if (UtilityRoutines::SameString(GAlphas(4), "World") || UtilityRoutines::SameString(GAlphas(4), "Absolute")) {
    3239           8 :                     state.dataSurface->DaylRefWorldCoordSystem = true;
    3240           8 :                     OutMsg += "WorldCoordinateSystem,";
    3241           8 :                     OK = true;
    3242             :                 }
    3243         771 :                 if (UtilityRoutines::SameString(GAlphas(4), "Relative") || GAlphas(4).empty()) {
    3244         763 :                     state.dataSurface->DaylRefWorldCoordSystem = false;
    3245         763 :                     OutMsg += "RelativeCoordinateSystem,";
    3246         763 :                     OK = true;
    3247             :                 }
    3248         771 :                 if (!OK) {
    3249           0 :                     ShowWarningError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + '=' + GAlphas(4));
    3250           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + " defaults to \"RelativeToZoneOrigin\"");
    3251           0 :                     state.dataSurface->DaylRefWorldCoordSystem = false;
    3252           0 :                     OutMsg += "RelativeToZoneOrigin,";
    3253             :                 }
    3254             : 
    3255         771 :                 OK = false;
    3256         771 :                 if (UtilityRoutines::SameString(GAlphas(5), "World") || UtilityRoutines::SameString(GAlphas(5), "Absolute")) {
    3257          17 :                     state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = true;
    3258          17 :                     OutMsg += "WorldCoordinateSystem";
    3259          17 :                     OK = true;
    3260             :                 }
    3261         771 :                 if (UtilityRoutines::SameString(GAlphas(5), "Relative") || GAlphas(5).empty()) {
    3262         754 :                     state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = false;
    3263         754 :                     OutMsg += "RelativeToZoneOrigin";
    3264         754 :                     OK = true;
    3265             :                 }
    3266         771 :                 if (!OK) {
    3267           0 :                     ShowWarningError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(5) + '=' + GAlphas(5));
    3268           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + " defaults to \"RelativeToZoneOrigin\"");
    3269           0 :                     state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = false;
    3270           0 :                     OutMsg += "RelativeToZoneOrigin";
    3271             :                 }
    3272             : 
    3273           0 :             } else if (SELECT_CASE_var == 0) {
    3274             : 
    3275           0 :                 ShowSevereError(state, cCurrentModuleObject + ": Required object not found.");
    3276           0 :                 OutMsg += "None found in input";
    3277           0 :                 ErrorsFound = true;
    3278             : 
    3279             :             } else {
    3280             : 
    3281           0 :                 ShowSevereError(state, cCurrentModuleObject + ": Too many objects entered.  Only one allowed.");
    3282           0 :                 ErrorsFound = true;
    3283             :             }
    3284             :         }
    3285             : 
    3286         771 :         if (!state.dataSurface->WorldCoordSystem) {
    3287         420 :             if (state.dataSurface->DaylRefWorldCoordSystem) {
    3288           0 :                 ShowWarningError(state, cCurrentModuleObject + ": Potential mismatch of coordinate specifications.");
    3289           0 :                 ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + GAlphas(3) + "\"; while ");
    3290           0 :                 ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + GAlphas(4) + "\".");
    3291             :             }
    3292         420 :             if (state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem) {
    3293           0 :                 ShowWarningError(state, cCurrentModuleObject + ": Potential mismatch of coordinate specifications.");
    3294           0 :                 ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + GAlphas(3) + "\"; while ");
    3295           0 :                 ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + GAlphas(5) + "\".");
    3296             :             }
    3297             :         } else {
    3298         351 :             RelWarning = false;
    3299        1372 :             for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    3300        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginX != 0.0) RelWarning = true;
    3301        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginY != 0.0) RelWarning = true;
    3302        1021 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginZ != 0.0) RelWarning = true;
    3303             :             }
    3304         351 :             if (RelWarning && !state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem) {
    3305           0 :                 ShowWarningError(state,
    3306           0 :                                  cCurrentModuleObject + ": Potential mismatch of coordinate specifications. Note that the rectangular surfaces are "
    3307             :                                                         "relying on the default SurfaceGeometry for 'Relative to zone' coordinate.");
    3308           0 :                 ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + GAlphas(3) + "\"; while ");
    3309           0 :                 if (GAlphas(5) == "RELATIVE") {
    3310           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + GAlphas(5) + "\".");
    3311           0 :                 } else if (GAlphas(5) != "ABSOLUTE") {
    3312           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"defaults to RELATIVE\".");
    3313             :                 }
    3314             :             }
    3315             :         }
    3316             : 
    3317         771 :         print(state.files.eio,
    3318             :               "! <Surface Geometry>,Starting Corner,Vertex Input Direction,Coordinate System,Daylight Reference "
    3319         771 :               "Point Coordinate System,Rectangular (Simple) Surface Coordinate System\n");
    3320         771 :         print(state.files.eio, "{}\n", OutMsg);
    3321         771 :     }
    3322             : 
    3323         771 :     void GetDetShdSurfaceData(EnergyPlusData &state,
    3324             :                               bool &ErrorsFound,          // Error flag indicator (true if errors found)
    3325             :                               int &SurfNum,               // Count of Current SurfaceNumber
    3326             :                               int const TotDetachedFixed, // Number of Fixed Detached Shading Surfaces to obtain
    3327             :                               int const TotDetachedBldg   // Number of Building Detached Shading Surfaces to obtain
    3328             :     )
    3329             :     {
    3330             :         // SUBROUTINE INFORMATION:
    3331             :         //       AUTHOR         Linda Lawrie
    3332             :         //       DATE WRITTEN   May 2000
    3333             : 
    3334             :         // PURPOSE OF THIS SUBROUTINE:
    3335             :         // This subroutine gets the Detached Shading Surface Data,
    3336             :         // checks it for errors, etc.
    3337             : 
    3338             :         // Using/Aliasing
    3339             :         using ScheduleManager::CheckScheduleValueMinMax;
    3340             :         using ScheduleManager::GetScheduleIndex;
    3341             :         using ScheduleManager::GetScheduleMaxValue;
    3342             :         using ScheduleManager::GetScheduleMinValue;
    3343             : 
    3344             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3345         771 :         static Array1D_string const cModuleObjects(2, {"Shading:Site:Detailed", "Shading:Building:Detailed"});
    3346             : 
    3347             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3348             :         int IOStat;     // IO Status when calling get input subroutine
    3349             :         int NumAlphas;  // Number of material alpha names being passed
    3350             :         int NumNumbers; // Number of material properties being passed
    3351             :         int Loop;
    3352             :         int Item;
    3353             :         int ItemsToGet;
    3354             :         SurfaceClass ClassItem;
    3355             :         int numSides;
    3356             :         Real64 SchedMinValue;
    3357             :         Real64 SchedMaxValue;
    3358             : 
    3359         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3360             : 
    3361         771 :         if ((TotDetachedFixed + TotDetachedBldg) > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    3362           0 :             ShowWarningError(state, "Detached shading effects are ignored when Solar Distribution = MinimalShadowing");
    3363             :         }
    3364             : 
    3365         771 :         if ((TotDetachedFixed + TotDetachedBldg) == 0) return;
    3366             : 
    3367          54 :         for (Item = 1; Item <= 2; ++Item) {
    3368             : 
    3369          36 :             cCurrentModuleObject = cModuleObjects(Item);
    3370          36 :             if (Item == 1) {
    3371          18 :                 ItemsToGet = TotDetachedFixed;
    3372          18 :                 ClassItem = SurfaceClass::Detached_F;
    3373             :             } else { // IF (Item == 2) THEN
    3374          18 :                 ItemsToGet = TotDetachedBldg;
    3375          18 :                 ClassItem = SurfaceClass::Detached_B;
    3376             :             }
    3377             : 
    3378          36 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
    3379          36 :             if (NumAlphas != 2) {
    3380           0 :                 ShowSevereError(
    3381           0 :                     state, format("{}: Object Definition indicates not = 2 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
    3382           0 :                 ErrorsFound = true;
    3383             :             }
    3384             : 
    3385          86 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    3386         350 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3387             :                                                                          cCurrentModuleObject,
    3388             :                                                                          Loop,
    3389          50 :                                                                          state.dataIPShortCut->cAlphaArgs,
    3390             :                                                                          NumAlphas,
    3391          50 :                                                                          state.dataIPShortCut->rNumericArgs,
    3392             :                                                                          NumNumbers,
    3393             :                                                                          IOStat,
    3394          50 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3395          50 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3396          50 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3397          50 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3398             : 
    3399         100 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    3400          50 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    3401          50 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    3402             :                                                              cCurrentModuleObject,
    3403          50 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    3404             :                                                              ErrorsFound)) {
    3405           0 :                     continue;
    3406             :                 }
    3407             : 
    3408          50 :                 ++SurfNum;
    3409          50 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    3410          50 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = ClassItem;
    3411          50 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    3412             :                 // Base transmittance of a shadowing (sub)surface
    3413          50 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    3414             :                     // Schedule for a shadowing (sub)surface
    3415          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex =
    3416          26 :                         GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    3417          26 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex == 0) {
    3418           0 :                         ShowSevereError(state,
    3419           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    3420           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + " not found=" + state.dataIPShortCut->cAlphaArgs(2));
    3421           0 :                         ErrorsFound = true;
    3422             :                     }
    3423             :                 } else {
    3424          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    3425             :                 }
    3426          50 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex != 0) {
    3427          26 :                     if (!CheckScheduleValueMinMax(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex, ">=", 0.0, "<=", 1.0)) {
    3428           0 :                         ShowSevereError(state,
    3429           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    3430           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    3431             :                                             "\", values not in range [0,1].");
    3432           0 :                         ErrorsFound = true;
    3433             :                     }
    3434          26 :                     SchedMinValue = GetScheduleMinValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    3435          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue = SchedMinValue;
    3436          26 :                     SchedMaxValue = GetScheduleMaxValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    3437          26 :                     if (SchedMinValue == 1.0) {
    3438           0 :                         ShowWarningError(state,
    3439           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    3440           0 :                                              state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    3441             :                                              "\", is always transparent.");
    3442           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent = true;
    3443             :                     }
    3444          26 :                     if (SchedMinValue < 0.0) {
    3445           0 :                         ShowSevereError(state,
    3446           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    3447           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    3448             :                                             "\", has schedule values < 0.");
    3449           0 :                         ShowContinueError(state, "...Schedule values < 0 have no meaning for shading elements.");
    3450             :                     }
    3451          26 :                     if (SchedMaxValue > 0.0) {
    3452          26 :                         state.dataSolarShading->anyScheduledShadingSurface = true;
    3453             :                     }
    3454          26 :                     if (SchedMaxValue > 1.0) {
    3455           0 :                         ShowSevereError(state,
    3456           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    3457           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    3458             :                                             "\", has schedule values > 1.");
    3459           0 :                         ShowContinueError(state, "...Schedule values > 1 have no meaning for shading elements.");
    3460             :                     }
    3461          26 :                     if (std::abs(SchedMinValue - SchedMaxValue) > 1.0e-6) {
    3462           0 :                         state.dataSurface->ShadingTransmittanceVaries = true;
    3463             :                     }
    3464             :                 }
    3465          50 :                 if (state.dataIPShortCut->lNumericFieldBlanks(1) || state.dataIPShortCut->rNumericArgs(1) == DataGlobalConstants::AutoCalculate) {
    3466           0 :                     numSides = (NumNumbers - 1) / 3;
    3467           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = numSides;
    3468           0 :                     if (mod(NumNumbers - 1, 3) != 0) {
    3469           0 :                         ShowWarningError(state,
    3470           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    3471           0 :                                              format("{} not even multiple of 3. Will read in {}",
    3472           0 :                                                     state.dataIPShortCut->cNumericFieldNames(1),
    3473           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    3474             :                     }
    3475           0 :                     if (numSides < 3) {
    3476           0 :                         ShowSevereError(state,
    3477           0 :                                         format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    3478             :                                                cCurrentModuleObject,
    3479           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3480           0 :                                                state.dataIPShortCut->cNumericFieldNames(1),
    3481           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    3482           0 :                         ErrorsFound = true;
    3483           0 :                         continue;
    3484             :                     }
    3485             :                 } else {
    3486          50 :                     numSides = (NumNumbers - 1) / 3;
    3487          50 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
    3488          50 :                     if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
    3489           0 :                         ShowWarningError(state,
    3490           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", field " +
    3491           0 :                                              state.dataIPShortCut->cNumericFieldNames(1) + '=' +
    3492           0 :                                              fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    3493           0 :                         ShowContinueError(state,
    3494           0 :                                           format("...but {} were entered. Only the indicated {} will be used.",
    3495             :                                                  numSides,
    3496           0 :                                                  state.dataIPShortCut->cNumericFieldNames(1)));
    3497             :                     }
    3498             :                 }
    3499          50 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    3500          50 :                 GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({2, _}));
    3501          50 :                 CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    3502          50 :                 if (state.dataReportFlag->MakeMirroredDetachedShading) {
    3503          50 :                     MakeMirrorSurface(state, SurfNum);
    3504             :                 }
    3505             :             }
    3506             : 
    3507             :         } // Item Loop
    3508             :     }
    3509             : 
    3510         771 :     void GetRectDetShdSurfaceData(EnergyPlusData &state,
    3511             :                                   bool &ErrorsFound,              // Error flag indicator (true if errors found)
    3512             :                                   int &SurfNum,                   // Count of Current SurfaceNumber
    3513             :                                   int const TotRectDetachedFixed, // Number of Fixed Detached Shading Surfaces to obtain
    3514             :                                   int const TotRectDetachedBldg   // Number of Building Detached Shading Surfaces to obtain
    3515             :     )
    3516             :     {
    3517             : 
    3518             :         // SUBROUTINE INFORMATION:
    3519             :         //       AUTHOR         Linda Lawrie
    3520             :         //       DATE WRITTEN   January 2009
    3521             :         //       MODIFIED       na
    3522             :         //       RE-ENGINEERED  na
    3523             : 
    3524             :         // PURPOSE OF THIS SUBROUTINE:
    3525             :         // Gets the simple, rectangular detached surfaces.
    3526             : 
    3527             :         // Using/Aliasing
    3528             : 
    3529             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3530         771 :         static Array1D_string const cModuleObjects(2, {"Shading:Site", "Shading:Building"});
    3531             : 
    3532             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3533             :         int IOStat;     // IO Status when calling get input subroutine
    3534             :         int NumAlphas;  // Number of material alpha names being passed
    3535             :         int NumNumbers; // Number of material properties being passed
    3536             :         int Loop;
    3537             :         int Item;
    3538             :         int ItemsToGet;
    3539             :         SurfaceClass ClassItem;
    3540             : 
    3541         771 :         if ((TotRectDetachedFixed + TotRectDetachedBldg) > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    3542           0 :             ShowWarningError(state, "Detached shading effects are ignored when Solar Distribution = MinimalShadowing");
    3543             :         }
    3544             : 
    3545         771 :         if (TotRectDetachedFixed + TotRectDetachedBldg == 0) return;
    3546           6 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3547          18 :         for (Item = 1; Item <= 2; ++Item) {
    3548             : 
    3549          12 :             cCurrentModuleObject = cModuleObjects(Item);
    3550          12 :             if (Item == 1) {
    3551           6 :                 ItemsToGet = TotRectDetachedFixed;
    3552           6 :                 ClassItem = SurfaceClass::Detached_F;
    3553             :             } else { // IF (Item == 2) THEN
    3554           6 :                 ItemsToGet = TotRectDetachedBldg;
    3555           6 :                 ClassItem = SurfaceClass::Detached_B;
    3556             :             }
    3557             : 
    3558          12 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
    3559          12 :             if (NumAlphas != 1) {
    3560           0 :                 ShowSevereError(
    3561           0 :                     state, format("{}: Object Definition indicates not = 1 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
    3562           0 :                 ErrorsFound = true;
    3563             :             }
    3564             : 
    3565          32 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    3566         140 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3567             :                                                                          cCurrentModuleObject,
    3568             :                                                                          Loop,
    3569          20 :                                                                          state.dataIPShortCut->cAlphaArgs,
    3570             :                                                                          NumAlphas,
    3571          20 :                                                                          state.dataIPShortCut->rNumericArgs,
    3572             :                                                                          NumNumbers,
    3573             :                                                                          IOStat,
    3574          20 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3575          20 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3576          20 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3577          20 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3578             : 
    3579          40 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    3580          20 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    3581          20 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    3582             :                                                              cCurrentModuleObject,
    3583          20 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    3584             :                                                              ErrorsFound)) {
    3585           0 :                     continue;
    3586             :                 }
    3587             : 
    3588          20 :                 ++SurfNum;
    3589          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    3590          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = ClassItem;
    3591          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    3592             : 
    3593          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataIPShortCut->rNumericArgs(1);
    3594          20 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B && !state.dataSurface->WorldCoordSystem) {
    3595           4 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingAzimuth;
    3596             :                 }
    3597          20 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    3598           6 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingRotationAppendixG;
    3599             :                 }
    3600          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataIPShortCut->rNumericArgs(2);
    3601          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    3602          20 :                     ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    3603             : 
    3604          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    3605          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    3606             : 
    3607         120 :                 MakeRectangularVertices(state,
    3608             :                                         SurfNum,
    3609          20 :                                         state.dataIPShortCut->rNumericArgs(3),
    3610          20 :                                         state.dataIPShortCut->rNumericArgs(4),
    3611          20 :                                         state.dataIPShortCut->rNumericArgs(5),
    3612          20 :                                         state.dataIPShortCut->rNumericArgs(6),
    3613          20 :                                         state.dataIPShortCut->rNumericArgs(7),
    3614          20 :                                         state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem);
    3615             : 
    3616          20 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    3617           0 :                     ShowSevereError(state,
    3618           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    3619             :                                            cCurrentModuleObject,
    3620           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3621           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    3622           0 :                     ErrorsFound = true;
    3623             :                 }
    3624             : 
    3625          20 :                 if (state.dataReportFlag->MakeMirroredDetachedShading) {
    3626          20 :                     MakeMirrorSurface(state, SurfNum);
    3627             :                 }
    3628             :             }
    3629             : 
    3630             :         } // Item Loop
    3631             :     }
    3632             : 
    3633         771 :     void GetHTSurfaceData(EnergyPlusData &state,
    3634             :                           bool &ErrorsFound,                 // Error flag indicator (true if errors found)
    3635             :                           int &SurfNum,                      // Count of Current SurfaceNumber
    3636             :                           int const TotHTSurfs,              // Number of Heat Transfer Base Surfaces to obtain
    3637             :                           int const TotDetailedWalls,        // Number of Wall:Detailed items to obtain
    3638             :                           int const TotDetailedRoofs,        // Number of RoofCeiling:Detailed items to obtain
    3639             :                           int const TotDetailedFloors,       // Number of Floor:Detailed items to obtain
    3640             :                           const Array1D_string &BaseSurfCls, // Valid Classes for Base Surfaces
    3641             :                           const Array1D<SurfaceClass> &BaseSurfIDs,
    3642             :                           int &NeedToAddSurfaces // Number of surfaces to add, based on unentered IZ surfaces
    3643             :     )
    3644             :     {
    3645             : 
    3646             :         // SUBROUTINE INFORMATION:
    3647             :         //       AUTHOR         Linda Lawrie
    3648             :         //       DATE WRITTEN   May 2000
    3649             :         //       MODIFIED       na
    3650             :         //       RE-ENGINEERED  na
    3651             : 
    3652             :         // PURPOSE OF THIS SUBROUTINE:
    3653             :         // This subroutine gets the HeatTransfer Surface Data,
    3654             :         // checks it for errors, etc.
    3655             : 
    3656             :         // METHODOLOGY EMPLOYED:
    3657             :         // na
    3658             : 
    3659             :         // REFERENCES:
    3660             :         // Heat Transfer Surface Definition
    3661             :         // BuildingSurface:Detailed,
    3662             :         //  \extensible:3 -- duplicate last set of x,y,z coordinates (last 3 fields), remembering to remove ; from "inner" fields.
    3663             :         //  \format vertices
    3664             :         //  A1 , \field Name
    3665             :         //       \required-field
    3666             :         //       \type alpha
    3667             :         //       \reference SurfaceNames
    3668             :         //       \reference SurfAndSubSurfNames
    3669             :         //       \reference AllHeatTranSurfNames
    3670             :         //       \reference HeatTranBaseSurfNames
    3671             :         //       \reference OutFaceEnvNames
    3672             :         //       \reference AllHeatTranAngFacNames
    3673             :         //       \reference RadGroupAndSurfNames
    3674             :         //       \reference SurfGroupAndHTSurfNames
    3675             :         //       \reference AllShadingAndHTSurfNames
    3676             :         //  A2 , \field Surface Type
    3677             :         //       \required-field
    3678             :         //       \type choice
    3679             :         //       \key Floor
    3680             :         //       \key Wall
    3681             :         //       \key Ceiling
    3682             :         //       \key Roof
    3683             :         //  A3 , \field Construction Name
    3684             :         //       \required-field
    3685             :         //       \note To be matched with a construction in this input file
    3686             :         //       \type object-list
    3687             :         //       \object-list ConstructionNames
    3688             :         //  A4 , \field Zone Name
    3689             :         //       \required-field
    3690             :         //       \note Zone the surface is a part of
    3691             :         //       \type object-list
    3692             :         //       \object-list ZoneNames
    3693             :         //  A5 , \field Outside Boundary Condition
    3694             :         //       \required-field
    3695             :         //       \type choice
    3696             :         //       \key Adiabatic
    3697             :         //       \key Surface
    3698             :         //       \key Zone
    3699             :         //       \key Outdoors
    3700             :         //       \key Ground
    3701             :         //       \key GroundFCfactorMethod
    3702             :         //       \key OtherSideCoefficients
    3703             :         //       \key OtherSideConditionsModel
    3704             :         //       \key GroundSlabPreprocessorAverage
    3705             :         //       \key GroundSlabPreprocessorCore
    3706             :         //       \key GroundSlabPreprocessorPerimeter
    3707             :         //       \key GroundBasementPreprocessorAverageWall
    3708             :         //       \key GroundBasementPreprocessorAverageFloor
    3709             :         //       \key GroundBasementPreprocessorUpperWall
    3710             :         //       \key GroundBasementPreprocessorLowerWall
    3711             :         //  A6,  \field Outside Boundary Condition Object
    3712             :         //       \type object-list
    3713             :         //       \object-list OutFaceEnvNames
    3714             :         //       \note Non-blank only if the field Outside Boundary Condition is Surface,
    3715             :         //       \note Zone, OtherSideCoefficients or OtherSideConditionsModel
    3716             :         //       \note If Surface, specify name of corresponding surface in adjacent zone or
    3717             :         //       \note specify current surface name for internal partition separating like zones
    3718             :         //       \note If Zone, specify the name of the corresponding zone and
    3719             :         //       \note the program will generate the corresponding interzone surface
    3720             :         //       \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
    3721             :         //       \note If OtherSideConditionsModel, specify name of SurfaceProperty:OtherSideConditionsModel
    3722             :         //  A7 , \field Sun Exposure
    3723             :         //       \required-field
    3724             :         //       \type choice
    3725             :         //       \key SunExposed
    3726             :         //       \key NoSun
    3727             :         //       \default SunExposed
    3728             :         //  A8,  \field Wind Exposure
    3729             :         //       \required-field
    3730             :         //       \type choice
    3731             :         //       \key WindExposed
    3732             :         //       \key NoWind
    3733             :         //       \default WindExposed
    3734             :         //  N1,  \field View Factor to Ground
    3735             :         //       \type real
    3736             :         //       \note From the exterior of the surface
    3737             :         //       \note Unused if one uses the "reflections" options in Solar Distribution in Building input
    3738             :         //       \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
    3739             :         //       \note autocalculate will automatically calculate this value from the tilt of the surface
    3740             :         //       \autocalculatable
    3741             :         //       \minimum 0.0
    3742             :         //       \maximum 1.0
    3743             :         //       \default autocalculate
    3744             :         //  N2 , \field Number of Vertices
    3745             :         //       \note shown with 120 vertex coordinates -- extensible object
    3746             :         //       \note  "extensible" -- duplicate last set of x,y,z coordinates (last 3 fields),
    3747             :         //       \note remembering to remove ; from "inner" fields.
    3748             :         //       \note for clarity in any error messages, renumber the fields as well.
    3749             :         //       \note (and changing z terminator to a comma "," for all but last one which needs a semi-colon ";")
    3750             :         //       \autocalculatable
    3751             :         //       \minimum 3
    3752             :         //       \default autocalculate
    3753             :         //       \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
    3754             :         //       \note are "relative" to the Zone Origin.  If world, then building and zone origins are used
    3755             :         //       \note for some internal calculations, but all coordinates are given in an "absolute" system.
    3756             :         //  N3-xx as indicated by the N3 value
    3757             : 
    3758             :         // Using/Aliasing
    3759             : 
    3760             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3761         771 :         static Array1D_string const cModuleObjects(4, {"BuildingSurface:Detailed", "Wall:Detailed", "Floor:Detailed", "RoofCeiling:Detailed"});
    3762             : 
    3763             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3764             :         int IOStat;          // IO Status when calling get input subroutine
    3765             :         int SurfaceNumAlpha; // Number of material alpha names being passed
    3766             :         int SurfaceNumProp;  // Number of material properties being passed
    3767             :         int ZoneNum;         // DO loop counter (zones)
    3768             :         int Found;           // For matching interzone surfaces
    3769             :         int Loop;
    3770             :         int Item;
    3771             :         int ItemsToGet;
    3772             :         int ClassItem;
    3773             :         int ArgPointer;
    3774             :         int numSides;
    3775             : 
    3776         771 :         GetOSCData(state, ErrorsFound);
    3777         771 :         GetOSCMData(state, ErrorsFound);
    3778         771 :         GetFoundationData(state, ErrorsFound);
    3779             : 
    3780         771 :         NeedToAddSurfaces = 0;
    3781         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3782        3855 :         for (Item = 1; Item <= 4; ++Item) {
    3783             : 
    3784        3084 :             cCurrentModuleObject = cModuleObjects(Item);
    3785        3084 :             if (Item == 1) {
    3786         771 :                 ItemsToGet = TotHTSurfs;
    3787         771 :                 ClassItem = 0;
    3788        2313 :             } else if (Item == 2) {
    3789         771 :                 ItemsToGet = TotDetailedWalls;
    3790         771 :                 ClassItem = 1;
    3791        1542 :             } else if (Item == 3) {
    3792         771 :                 ItemsToGet = TotDetailedFloors;
    3793         771 :                 ClassItem = 2;
    3794             :             } else { // IF (Item == 4) THEN
    3795         771 :                 ItemsToGet = TotDetailedRoofs;
    3796         771 :                 ClassItem = 3;
    3797             :             }
    3798             : 
    3799        3084 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, SurfaceNumAlpha, SurfaceNumProp);
    3800        3084 :             if (Item == 1) {
    3801         771 :                 if (SurfaceNumAlpha != 9) {
    3802           0 :                     ShowSevereError(
    3803             :                         state,
    3804           0 :                         format("{}: Object Definition indicates not = 9 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    3805           0 :                     ErrorsFound = true;
    3806             :                 }
    3807             :             } else {
    3808        2313 :                 if (SurfaceNumAlpha != 8) {
    3809           0 :                     ShowSevereError(
    3810             :                         state,
    3811           0 :                         format("{}: Object Definition indicates not = 8 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    3812           0 :                     ErrorsFound = true;
    3813             :                 }
    3814             :             }
    3815             : 
    3816       36095 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    3817      231077 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3818             :                                                                          cCurrentModuleObject,
    3819             :                                                                          Loop,
    3820       33011 :                                                                          state.dataIPShortCut->cAlphaArgs,
    3821             :                                                                          SurfaceNumAlpha,
    3822       33011 :                                                                          state.dataIPShortCut->rNumericArgs,
    3823             :                                                                          SurfaceNumProp,
    3824             :                                                                          IOStat,
    3825       33011 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3826       33011 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3827       33011 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3828       33011 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3829             : 
    3830       66022 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    3831       33011 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    3832       33011 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    3833             :                                                              cCurrentModuleObject,
    3834       33011 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    3835             :                                                              ErrorsFound)) {
    3836           0 :                     continue;
    3837             :                 }
    3838             : 
    3839       33011 :                 ++SurfNum;
    3840       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    3841       33011 :                 ArgPointer = 2;
    3842       33011 :                 if (Item == 1) {
    3843       32987 :                     if (state.dataIPShortCut->cAlphaArgs(2) == "CEILING") state.dataIPShortCut->cAlphaArgs(2) = "ROOF";
    3844       32987 :                     ClassItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), BaseSurfCls, 3);
    3845       32987 :                     if (ClassItem == 0) {
    3846           0 :                         ShowSevereError(state,
    3847           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3848           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    3849           0 :                         ErrorsFound = true;
    3850             :                     } else {
    3851       32987 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);
    3852             :                     }
    3853       32987 :                     ++ArgPointer;
    3854             :                 } else {
    3855          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);
    3856             :                 }
    3857             : 
    3858       99033 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
    3859       99033 :                     state.dataIPShortCut->cAlphaArgs(ArgPointer), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    3860             : 
    3861       33011 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    3862           0 :                     ErrorsFound = true;
    3863           0 :                     ShowSevereError(state,
    3864           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3865           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    3866             :                                         "\".");
    3867       33011 :                 } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    3868           0 :                     ErrorsFound = true;
    3869           0 :                     ShowSevereError(state,
    3870           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3871           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    3872             :                                         "\" - has Window materials.");
    3873           0 :                     if (Item == 1) {
    3874           0 :                         ShowContinueError(state,
    3875           0 :                                           "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
    3876             :                     } else {
    3877           0 :                         ShowContinueError(state, "...because Surface Type=" + BaseSurfCls(ClassItem));
    3878             :                     }
    3879             :                 } else {
    3880       33011 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    3881       33011 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    3882       33011 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    3883             :                 }
    3884       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    3885       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
    3886       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    3887             : 
    3888       33011 :                 ++ArgPointer;
    3889       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataIPShortCut->cAlphaArgs(ArgPointer);
    3890       99033 :                 ZoneNum = UtilityRoutines::FindItemInList(
    3891       99033 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    3892             : 
    3893       33011 :                 if (ZoneNum != 0) {
    3894       33011 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
    3895             :                 } else {
    3896           0 :                     ShowSevereError(state,
    3897           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3898           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    3899             :                                         "\".");
    3900           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    3901           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    3902           0 :                     ErrorsFound = true;
    3903             :                 }
    3904             : 
    3905       33011 :                 ++ArgPointer;
    3906       33011 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer)) {
    3907          25 :                     int spaceNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(ArgPointer), state.dataHeatBal->space);
    3908             : 
    3909          25 :                     if (spaceNum != 0) {
    3910          25 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
    3911          25 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone != state.dataHeatBal->space(spaceNum).zoneNum) {
    3912           0 :                             ShowSevereError(state,
    3913           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3914           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
    3915           0 :                                                 state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\" is not in the same zone as the surface.");
    3916           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    3917           0 :                             ErrorsFound = true;
    3918             :                         }
    3919             :                     } else {
    3920           0 :                         ShowSevereError(state,
    3921           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3922           0 :                                             state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
    3923           0 :                                             state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\" not found.");
    3924           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    3925           0 :                         ErrorsFound = true;
    3926             :                     }
    3927             :                 }
    3928             :                 // Get the ExteriorBoundaryCondition flag from input There are 4 conditions that
    3929             :                 // can take place. The conditions are set with a 0, -1, or -2, or all of the
    3930             :                 // zone names have to be looked at and generate the interzone array number
    3931       33011 :                 ++ArgPointer;
    3932       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(ArgPointer + 1);
    3933             : 
    3934       33011 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Outdoors")) {
    3935       10666 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    3936             : 
    3937       22345 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Adiabatic")) {
    3938        1259 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    3939        1259 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    3940             : 
    3941       21086 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Ground")) {
    3942        2110 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = Ground;
    3943             : 
    3944        2110 :                     if (state.dataSurfaceGeometry->NoGroundTempObjWarning) {
    3945         421 :                         if (!state.dataEnvrn->GroundTempObjInput) {
    3946           1 :                             ShowWarningError(state,
    3947             :                                              "GetHTSurfaceData: Surfaces with interface to Ground found but no \"Ground Temperatures\" were input.");
    3948           1 :                             ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
    3949           3 :                             ShowContinueError(
    3950           2 :                                 state, format("Defaults, constant throughout the year of ({:.1R}) will be used.", state.dataEnvrn->GroundTemp));
    3951             :                         }
    3952         421 :                         state.dataSurfaceGeometry->NoGroundTempObjWarning = false;
    3953             :                     }
    3954             : 
    3955             :                     // Added for FCfactor method
    3956       18976 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundFCfactorMethod")) {
    3957         179 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
    3958         179 :                     if (state.dataSurfaceGeometry->NoFCGroundTempObjWarning) {
    3959         179 :                         if (!state.dataEnvrn->FCGroundTemps) {
    3960           0 :                             ShowSevereError(state,
    3961             :                                             "GetHTSurfaceData: Surfaces with interface to GroundFCfactorMethod found but no \"FC Ground "
    3962             :                                             "Temperatures\" were input.");
    3963           0 :                             ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
    3964           0 :                             ShowContinueError(state,
    3965             :                                               "Either add a \"Site:GroundTemperature:FCfactorMethod\" object or use a weather file with "
    3966             :                                               "Ground Temperatures.");
    3967           0 :                             ErrorsFound = true;
    3968           0 :                             state.dataSurfaceGeometry->NoFCGroundTempObjWarning = false;
    3969             :                         }
    3970             :                     }
    3971         179 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
    3972         213 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    3973          34 :                             !state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
    3974           0 :                             ShowSevereError(state,
    3975           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3976           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(ArgPointer));
    3977           0 :                             ShowContinueError(
    3978             :                                 state,
    3979           0 :                                 "Construction=\"" +
    3980           0 :                                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name +
    3981             :                                     "\" is not type Construction:CfactorUndergroundWall.");
    3982           0 :                             ErrorsFound = true;
    3983             :                         }
    3984         324 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    3985         145 :                             !state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
    3986           0 :                             ShowSevereError(state,
    3987           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    3988           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(ArgPointer));
    3989           0 :                             ShowContinueError(
    3990             :                                 state,
    3991           0 :                                 "Construction=\"" +
    3992           0 :                                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name +
    3993             :                                     "\" is not type Construction:FfactorGroundFloor.");
    3994           0 :                             ErrorsFound = true;
    3995             :                         }
    3996             :                     }
    3997             : 
    3998       18797 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "OtherSideCoefficients")) {
    3999          51 :                     Found = UtilityRoutines::FindItemInList(
    4000          51 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataSurface->OSC, state.dataSurface->TotOSC);
    4001          17 :                     if (Found == 0) {
    4002           0 :                         ShowSevereError(state,
    4003           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4004           0 :                                             state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=\"" +
    4005           0 :                                             state.dataIPShortCut->cAlphaArgs(ArgPointer + 1) + "\".");
    4006           0 :                         ShowContinueError(state, " no OtherSideCoefficients of that name.");
    4007           0 :                         ErrorsFound = true;
    4008             :                     } else {
    4009          17 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
    4010          17 :                         if (state.dataSurface->OSC(Found).SurfFilmCoef > 0.0) {
    4011           1 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefCalcExt;
    4012             :                         } else {
    4013          16 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefNoCalcExt;
    4014             :                         }
    4015             :                     }
    4016             : 
    4017       18780 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Surface")) {
    4018             :                     // it has to be another surface which needs to be found
    4019             :                     // this will be found on the second pass through the surface input
    4020             :                     // for flagging, set the value to UnreconciledZoneSurface
    4021             :                     // name (ExtBoundCondName) will be validated later.
    4022       18337 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    4023       18337 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer + 1)) {
    4024           6 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    4025          18 :                         ShowSevereError(state,
    4026          12 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4027          18 :                                             state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=<blank>.");
    4028           6 :                         ShowContinueError(state, ".." + state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"Surface\" must be non-blank.");
    4029           6 :                         ShowContinueError(state, "..This surface will become an adiabatic surface - no doors/windows allowed.");
    4030             :                     }
    4031             : 
    4032         443 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Zone")) {
    4033             :                     // This is the code for an unmatched "other surface"
    4034             :                     // will be set up later.
    4035         363 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    4036             :                     // check OutsideFaceEnvironment for legal zone
    4037        1089 :                     Found = UtilityRoutines::FindItemInList(
    4038        1089 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    4039         363 :                     ++NeedToAddSurfaces;
    4040             : 
    4041         363 :                     if (Found == 0) {
    4042           0 :                         ShowSevereError(state,
    4043           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4044           0 :                                             state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
    4045           0 :                                             state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\".");
    4046           0 :                         ShowContinueError(state, "..Referenced as Zone for this surface.");
    4047           0 :                         ErrorsFound = true;
    4048             :                     }
    4049             : 
    4050          80 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Foundation")) {
    4051             : 
    4052          38 :                     if (!state.dataWeatherManager->WeatherFileExists) {
    4053           0 :                         ShowSevereError(state,
    4054           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    4055             :                                             "\", using \"Foundation\" type Outside Boundary Condition requires specification of a weather file");
    4056           0 :                         ShowContinueError(state,
    4057             :                                           "Either place in.epw in the working directory or specify a weather file on the command line using -w "
    4058             :                                           "/path/to/weather.epw");
    4059           0 :                         ErrorsFound = true;
    4060             :                     }
    4061             : 
    4062             :                     // Find foundation object, if blank use default
    4063          38 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer + 1)) {
    4064             : 
    4065           8 :                         if (!state.dataSurfaceGeometry->kivaManager.defaultAdded) {
    4066             :                             // Add default foundation if no other foundation object specified
    4067           2 :                             state.dataSurfaceGeometry->kivaManager.addDefaultFoundation();
    4068             :                         }
    4069           8 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr =
    4070           8 :                             state.dataSurfaceGeometry->kivaManager.defaultIndex; // Reuse OSC pointer...shouldn't be used for non OSC surfaces anyway.
    4071             :                     } else {
    4072          30 :                         Found =
    4073          30 :                             state.dataSurfaceGeometry->kivaManager.findFoundation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName);
    4074          30 :                         if (Found != (int)state.dataSurfaceGeometry->kivaManager.foundationInputs.size()) {
    4075          30 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
    4076             :                         } else {
    4077           0 :                             ShowSevereError(state,
    4078           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4079           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=\"" +
    4080           0 :                                                 state.dataIPShortCut->cAlphaArgs(ArgPointer + 1) + "\".");
    4081           0 :                             ErrorsFound = true;
    4082             :                         }
    4083             :                     }
    4084             : 
    4085          38 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
    4086           0 :                         ShowSevereError(state,
    4087           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    4088             :                                             "\", construction may not have an internal source/sink");
    4089           0 :                         ErrorsFound = true;
    4090             :                     }
    4091          38 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = KivaFoundation;
    4092             : 
    4093          42 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "OtherSideConditionsModel")) {
    4094         126 :                     Found = UtilityRoutines::FindItemInList(
    4095         126 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataSurface->OSCM, state.dataSurface->TotOSCM);
    4096          42 :                     if (Found == 0) {
    4097           0 :                         ShowSevereError(state,
    4098           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4099           0 :                                             state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=\"" +
    4100           0 :                                             state.dataIPShortCut->cAlphaArgs(ArgPointer + 1) + "\".");
    4101           0 :                         ErrorsFound = true;
    4102             :                     }
    4103          42 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCMPtr = Found;
    4104          42 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCondModeledExt;
    4105             : 
    4106           0 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorAverage") ||
    4107           0 :                            UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorCore") ||
    4108           0 :                            UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorPerimeter") ||
    4109           0 :                            UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorAverageFloor") ||
    4110           0 :                            UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorAverageWall") ||
    4111           0 :                            UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorUpperWall") ||
    4112           0 :                            UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorLowerWall")) {
    4113           0 :                     ShowSevereError(state,
    4114           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4115           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    4116             :                                         "\".");
    4117           0 :                     ShowContinueError(state, "The ExpandObjects program has not been run or is not in your EnergyPlus.exe folder.");
    4118           0 :                     ErrorsFound = true;
    4119             : 
    4120             :                 } else {
    4121           0 :                     ShowSevereError(state,
    4122           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4123           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    4124             :                                         "\".");
    4125           0 :                     ShowContinueError(state,
    4126             :                                       "Should be one of \"Outdoors\", \"Adiabatic\", Ground\", \"Surface\", \"OtherSideCoefficients\", "
    4127             :                                       "\"OtherSideConditionsModel\" or \"Zone\"");
    4128           0 :                     ErrorsFound = true;
    4129             :                 } // ... End of the ExtBoundCond logical IF Block
    4130             : 
    4131       33011 :                 ArgPointer += 2;
    4132             :                 // Set the logical flag for the exterior solar
    4133       33011 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "SunExposed")) {
    4134       10574 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment) &&
    4135          16 :                         (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != OtherSideCondModeledExt)) {
    4136           0 :                         ShowWarningError(state,
    4137           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    4138           0 :                                              state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
    4139           0 :                                              state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\".");
    4140           0 :                         ShowContinueError(state, "..This surface is not exposed to External Environment.  Sun exposure has no effect.");
    4141             :                     } else {
    4142       10558 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
    4143             :                     }
    4144       22453 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "NoSun")) {
    4145       22453 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
    4146             :                 } else {
    4147           0 :                     ShowSevereError(state,
    4148           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4149           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    4150             :                                         "\".");
    4151           0 :                     ErrorsFound = true;
    4152             :                 }
    4153             : 
    4154       33011 :                 ++ArgPointer;
    4155             :                 // Set the logical flag for the exterior wind
    4156       33011 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "WindExposed")) {
    4157       10626 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = true;
    4158       22385 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "NoWind")) {
    4159       22385 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
    4160             :                 } else {
    4161           0 :                     ShowSevereError(state,
    4162           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4163           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
    4164             :                                         "\".");
    4165           0 :                     ErrorsFound = true;
    4166             :                 }
    4167             : 
    4168             :                 // Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
    4169             :                 //                if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0)
    4170             :                 //                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof =
    4171             :                 //                        state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof;
    4172             : 
    4173       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataIPShortCut->rNumericArgs(1);
    4174       33011 :                 if (state.dataIPShortCut->lNumericFieldBlanks(1))
    4175         142 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = DataGlobalConstants::AutoCalculate;
    4176       33011 :                 if (state.dataIPShortCut->lNumericFieldBlanks(2) || state.dataIPShortCut->rNumericArgs(2) == DataGlobalConstants::AutoCalculate) {
    4177         263 :                     numSides = (SurfaceNumProp - 2) / 3;
    4178         263 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = numSides;
    4179         263 :                     if (mod(SurfaceNumProp - 2, 3) != 0) {
    4180           0 :                         ShowWarningError(state,
    4181           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    4182           0 :                                              format("{} not even multiple of 3. Will read in {}",
    4183           0 :                                                     state.dataIPShortCut->cNumericFieldNames(2),
    4184           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    4185             :                     }
    4186         263 :                     if (numSides < 3) {
    4187           0 :                         ShowSevereError(state,
    4188           0 :                                         format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    4189             :                                                cCurrentModuleObject,
    4190           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4191           0 :                                                state.dataIPShortCut->cNumericFieldNames(2),
    4192           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    4193           0 :                         ErrorsFound = true;
    4194           0 :                         continue;
    4195             :                     }
    4196             :                 } else {
    4197       32748 :                     numSides = (SurfaceNumProp - 2) / 3;
    4198       32748 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(2);
    4199       32748 :                     if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
    4200           0 :                         ShowWarningError(state,
    4201           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", field " +
    4202           0 :                                              state.dataIPShortCut->cNumericFieldNames(2) + '=' +
    4203           0 :                                              fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    4204           0 :                         ShowContinueError(state,
    4205           0 :                                           format("...but {} were entered. Only the indicated {} will be used.",
    4206             :                                                  numSides,
    4207           0 :                                                  state.dataIPShortCut->cNumericFieldNames(2)));
    4208             :                     }
    4209             :                 }
    4210       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4211       33011 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewVertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4212       33011 :                 GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({3, _}));
    4213       33011 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    4214           0 :                     ShowSevereError(state,
    4215           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    4216             :                                            cCurrentModuleObject,
    4217           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4218           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4219           0 :                     ErrorsFound = true;
    4220             :                 }
    4221             : 
    4222       33011 :                 CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4223       33011 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "Surface")) {
    4224          16 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides !=
    4225           8 :                         static_cast<int>(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.size())) {
    4226           0 :                         ShowSevereError(state,
    4227           0 :                                         format("{}=\"{}\", After CheckConvexity, mismatch between Sides ({}) and size of Vertex ({}).",
    4228             :                                                cCurrentModuleObject,
    4229           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4230           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4231           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.size()));
    4232           0 :                         ShowContinueError(state, "CheckConvexity is used to verify the convexity of a surface and detect collinear points.");
    4233           0 :                         ErrorsFound = true;
    4234             :                     }
    4235             :                 }
    4236       33011 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
    4237             :                     // Check wall height for the CFactor walls
    4238             : 
    4239       54160 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    4240       21149 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
    4241         102 :                         if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height -
    4242          68 :                                      state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Height) > 0.05) {
    4243           0 :                             ShowWarningError(state,
    4244           0 :                                              format("{}=\"{}\", underground Wall Height = {:.2T}",
    4245             :                                                     cCurrentModuleObject,
    4246           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4247           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height));
    4248           0 :                             ShowContinueError(state, "..which does not match its construction height.");
    4249             :                         }
    4250             :                     }
    4251             : 
    4252             :                     // Check area and perimeter for the FFactor floors
    4253       39418 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    4254        6407 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
    4255         537 :                         if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area -
    4256         358 :                                      state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Area) > 0.1) {
    4257           0 :                             ShowWarningError(state,
    4258           0 :                                              format("{}=\"{}\", underground Floor Area = {:.2T}",
    4259             :                                                     cCurrentModuleObject,
    4260           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4261           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4262           0 :                             ShowContinueError(state, "..which does not match its construction area.");
    4263             :                         }
    4264         358 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter <
    4265         179 :                             state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).PerimeterExposed - 0.1) {
    4266           0 :                             ShowWarningError(state,
    4267           0 :                                              format("{}=\"{}\", underground Floor Perimeter = {:.2T}",
    4268             :                                                     cCurrentModuleObject,
    4269           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4270           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter));
    4271           0 :                             ShowContinueError(state, "..which is less than its construction exposed perimeter.");
    4272             :                         }
    4273             :                     }
    4274             :                 }
    4275             :             }
    4276             :         } // Item Looop
    4277             :         // Check number of Vertex between base surface and Outside Boundary surface
    4278             :         int ExtSurfNum;
    4279       33922 :         for (int i = 1; i <= SurfNum; i++) {
    4280       52747 :             if (state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCond == UnreconciledZoneSurface &&
    4281       19596 :                 state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName != "") {
    4282       19596 :                 ExtSurfNum =
    4283       19596 :                     UtilityRoutines::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName, state.dataSurfaceGeometry->SurfaceTmp);
    4284             :                 // If we cannot find the referenced surface
    4285       19596 :                 if (ExtSurfNum == 0) {
    4286           0 :                     ShowSevereError(state,
    4287           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(i).Name +
    4288           0 :                                         "\" references an outside boundary surface that cannot be found:" +
    4289           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName);
    4290           0 :                     ErrorsFound = true;
    4291             :                     // If vertex size mistmatch
    4292       39192 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(i).Vertex.size() !=
    4293       19596 :                            state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Vertex.size()) {
    4294           0 :                     ShowSevereError(state,
    4295           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(i).Name +
    4296           0 :                                         "\", Vertex size mismatch between base surface :" + state.dataSurfaceGeometry->SurfaceTmp(i).Name +
    4297           0 :                                         " and outside boundary surface: " + state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Name);
    4298           0 :                     ShowContinueError(state,
    4299           0 :                                       format("The vertex sizes are {} for base surface and {} for outside boundary surface. Please check inputs.",
    4300           0 :                                              state.dataSurfaceGeometry->SurfaceTmp(i).Vertex.size(),
    4301           0 :                                              state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Vertex.size()));
    4302           0 :                     ErrorsFound = true;
    4303             :                 }
    4304             :             }
    4305             :         }
    4306         771 :     }
    4307             : 
    4308         771 :     void GetRectSurfaces(EnergyPlusData &state,
    4309             :                          bool &ErrorsFound,                        // Error flag indicator (true if errors found)
    4310             :                          int &SurfNum,                             // Count of Current SurfaceNumber
    4311             :                          int const TotRectExtWalls,                // Number of Exterior Walls to obtain
    4312             :                          int const TotRectIntWalls,                // Number of Adiabatic Walls to obtain
    4313             :                          int const TotRectIZWalls,                 // Number of Interzone Walls to obtain
    4314             :                          int const TotRectUGWalls,                 // Number of Underground to obtain
    4315             :                          int const TotRectRoofs,                   // Number of Roofs to obtain
    4316             :                          int const TotRectCeilings,                // Number of Adiabatic Ceilings to obtain
    4317             :                          int const TotRectIZCeilings,              // Number of Interzone Ceilings to obtain
    4318             :                          int const TotRectGCFloors,                // Number of Floors with Ground Contact to obtain
    4319             :                          int const TotRectIntFloors,               // Number of Adiabatic Walls to obtain
    4320             :                          int const TotRectIZFloors,                // Number of Interzone Floors to obtain
    4321             :                          const Array1D<SurfaceClass> &BaseSurfIDs, // ID Assignments for valid surface classes
    4322             :                          int &NeedToAddSurfaces                    // Number of surfaces to add, based on unentered IZ surfaces
    4323             :     )
    4324             :     {
    4325             : 
    4326             :         // SUBROUTINE INFORMATION:
    4327             :         //       AUTHOR         Linda Lawrie
    4328             :         //       DATE WRITTEN   December 2008
    4329             :         //       MODIFIED       na
    4330             :         //       RE-ENGINEERED  na
    4331             : 
    4332             :         // PURPOSE OF THIS SUBROUTINE:
    4333             :         // Get simple (rectangular, LLC corner specified) walls
    4334             : 
    4335             :         // Using/Aliasing
    4336             : 
    4337             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4338             :         static Array1D_string const cModuleObjects(10,
    4339             :                                                    {"Wall:Exterior",
    4340             :                                                     "Wall:Adiabatic",
    4341             :                                                     "Wall:Interzone",
    4342             :                                                     "Wall:Underground",
    4343             :                                                     "Roof",
    4344             :                                                     "Ceiling:Adiabatic",
    4345             :                                                     "Ceiling:Interzone",
    4346             :                                                     "Floor:GroundContact",
    4347             :                                                     "Floor:Adiabatic",
    4348         771 :                                                     "Floor:Interzone"});
    4349             : 
    4350             :         int Item;
    4351             :         int ItemsToGet;
    4352             :         int Loop;
    4353             :         int NumAlphas;
    4354             :         int NumNumbers;
    4355             :         int IOStat; // IO Status when calling get input subroutine
    4356             :         int Found;  // For matching base surfaces
    4357             :         bool GettingIZSurfaces;
    4358             :         int OtherSurfaceField;
    4359             :         int ExtBoundCondition;
    4360             :         int ClassItem;
    4361             :         int ZoneNum;
    4362         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    4363        8481 :         for (Item = 1; Item <= 10; ++Item) {
    4364             : 
    4365        7710 :             cCurrentModuleObject = cModuleObjects(Item);
    4366        7710 :             if (Item == 1) {
    4367         771 :                 ItemsToGet = TotRectExtWalls;
    4368         771 :                 GettingIZSurfaces = false;
    4369         771 :                 OtherSurfaceField = 0;
    4370         771 :                 ExtBoundCondition = ExternalEnvironment;
    4371         771 :                 ClassItem = 1;
    4372        6939 :             } else if (Item == 2) {
    4373         771 :                 ItemsToGet = TotRectIntWalls;
    4374         771 :                 GettingIZSurfaces = false;
    4375         771 :                 OtherSurfaceField = 0;
    4376         771 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4377         771 :                 ClassItem = 1;
    4378        6168 :             } else if (Item == 3) {
    4379         771 :                 ItemsToGet = TotRectIZWalls;
    4380         771 :                 GettingIZSurfaces = true;
    4381         771 :                 OtherSurfaceField = 5;
    4382         771 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4383         771 :                 ClassItem = 1;
    4384        5397 :             } else if (Item == 4) {
    4385         771 :                 ItemsToGet = TotRectUGWalls;
    4386         771 :                 GettingIZSurfaces = false;
    4387         771 :                 OtherSurfaceField = 0;
    4388         771 :                 ExtBoundCondition = Ground;
    4389         771 :                 ClassItem = 1;
    4390        4626 :             } else if (Item == 5) {
    4391         771 :                 ItemsToGet = TotRectRoofs;
    4392         771 :                 GettingIZSurfaces = false;
    4393         771 :                 OtherSurfaceField = 0;
    4394         771 :                 ExtBoundCondition = ExternalEnvironment;
    4395         771 :                 ClassItem = 3;
    4396        3855 :             } else if (Item == 6) {
    4397         771 :                 ItemsToGet = TotRectCeilings;
    4398         771 :                 GettingIZSurfaces = false;
    4399         771 :                 OtherSurfaceField = 0;
    4400         771 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4401         771 :                 ClassItem = 3;
    4402        3084 :             } else if (Item == 7) {
    4403         771 :                 ItemsToGet = TotRectIZCeilings;
    4404         771 :                 GettingIZSurfaces = false;
    4405         771 :                 OtherSurfaceField = 5;
    4406         771 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4407         771 :                 ClassItem = 3;
    4408        2313 :             } else if (Item == 8) {
    4409         771 :                 ItemsToGet = TotRectGCFloors;
    4410         771 :                 GettingIZSurfaces = false;
    4411         771 :                 OtherSurfaceField = 0;
    4412         771 :                 ExtBoundCondition = Ground;
    4413         771 :                 ClassItem = 2;
    4414        1542 :             } else if (Item == 9) {
    4415         771 :                 ItemsToGet = TotRectIntFloors;
    4416         771 :                 GettingIZSurfaces = false;
    4417         771 :                 OtherSurfaceField = 0;
    4418         771 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4419         771 :                 ClassItem = 2;
    4420             :             } else { // IF (Item == 10) THEN
    4421         771 :                 ItemsToGet = TotRectIZFloors;
    4422         771 :                 GettingIZSurfaces = true;
    4423         771 :                 OtherSurfaceField = 5;
    4424         771 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4425         771 :                 ClassItem = 2;
    4426             :             }
    4427             : 
    4428        7829 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    4429         833 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4430             :                                                                          cCurrentModuleObject,
    4431             :                                                                          Loop,
    4432         119 :                                                                          state.dataIPShortCut->cAlphaArgs,
    4433             :                                                                          NumAlphas,
    4434         119 :                                                                          state.dataIPShortCut->rNumericArgs,
    4435             :                                                                          NumNumbers,
    4436             :                                                                          IOStat,
    4437         119 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    4438         119 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    4439         119 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    4440         119 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    4441             : 
    4442         238 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    4443         119 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    4444         119 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    4445             :                                                              cCurrentModuleObject,
    4446         119 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    4447             :                                                              ErrorsFound)) {
    4448           0 :                     continue;
    4449             :                 }
    4450             : 
    4451         119 :                 if (NumNumbers < 7) {
    4452           0 :                     ShowSevereError(state,
    4453           0 :                                     format("{}=\"{}\", Too few number of numeric args=[{}].",
    4454             :                                            cCurrentModuleObject,
    4455           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    4456           0 :                                            NumNumbers));
    4457           0 :                     ErrorsFound = true;
    4458             :                 }
    4459             : 
    4460         119 :                 ++SurfNum;
    4461         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    4462         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);             // Set class number
    4463             : 
    4464         357 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
    4465         357 :                     state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    4466             : 
    4467         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    4468           0 :                     ErrorsFound = true;
    4469           0 :                     ShowSevereError(state,
    4470           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4471           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
    4472         119 :                 } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    4473           0 :                     ErrorsFound = true;
    4474           0 :                     ShowSevereError(state,
    4475           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4476           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    4477             :                                         "\" - has Window materials.");
    4478           0 :                     ShowContinueError(state, "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
    4479             :                 } else {
    4480         119 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    4481         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    4482         119 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    4483             :                 }
    4484         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    4485         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
    4486         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    4487             : 
    4488         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataIPShortCut->cAlphaArgs(3);
    4489         357 :                 ZoneNum = UtilityRoutines::FindItemInList(
    4490         357 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    4491             : 
    4492         119 :                 if (ZoneNum != 0) {
    4493         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
    4494             :                 } else {
    4495           0 :                     ShowSevereError(state,
    4496           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4497           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
    4498           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    4499           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    4500           0 :                     ErrorsFound = true;
    4501             :                 }
    4502             : 
    4503         119 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    4504           0 :                     int spaceNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
    4505             : 
    4506           0 :                     if (spaceNum != 0) {
    4507           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
    4508             :                     } else {
    4509           0 :                         ShowSevereError(state,
    4510           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    4511           0 :                                             state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
    4512           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    4513           0 :                         ErrorsFound = true;
    4514             :                     }
    4515             :                 }
    4516             : 
    4517         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExtBoundCondition;
    4518         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
    4519         317 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    4520         119 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall &&
    4521           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    4522           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
    4523         119 :                     } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
    4524           0 :                         ErrorsFound = true;
    4525           0 :                         ShowSevereError(state,
    4526           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    4527             :                                             "\", Construction type is \"Construction:CfactorUndergroundWall\" but invalid for this object.");
    4528             :                     }
    4529         258 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    4530         119 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor &&
    4531           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    4532           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
    4533         119 :                     } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
    4534           0 :                         ErrorsFound = true;
    4535           0 :                         ShowSevereError(state,
    4536           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    4537             :                                             "\", Construction type is \"Construction:FfactorGroundFloor\" but invalid for this object.");
    4538             :                     }
    4539             :                 }
    4540         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
    4541         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
    4542         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = DataGlobalConstants::AutoCalculate;
    4543             : 
    4544         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
    4545          66 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
    4546          66 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = true;
    4547             : 
    4548             :                     // Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
    4549             :                     //                    if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0)
    4550             :                     //                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof =
    4551             :                     //                            state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof;
    4552             : 
    4553          53 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    4554          47 :                     if (GettingIZSurfaces) {
    4555          19 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(OtherSurfaceField);
    4556          57 :                         Found = UtilityRoutines::FindItemInList(
    4557          57 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    4558             :                         // see if match to zone, then it's an unentered other surface, else reconciled later
    4559          19 :                         if (Found > 0) {
    4560           1 :                             ++NeedToAddSurfaces;
    4561           1 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    4562             :                         }
    4563             :                     } else {
    4564          28 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    4565             :                     }
    4566             : 
    4567           6 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    4568             : 
    4569           6 :                     if (state.dataSurfaceGeometry->NoGroundTempObjWarning) {
    4570           1 :                         if (!state.dataEnvrn->GroundTempObjInput) {
    4571           0 :                             ShowWarningError(state,
    4572             :                                              "GetRectSurfaces: Surfaces with interface to Ground found but no \"Ground Temperatures\" were input.");
    4573           0 :                             ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
    4574           0 :                             ShowContinueError(
    4575           0 :                                 state, format("Defaults, constant throughout the year of ({:.1R}) will be used.", state.dataEnvrn->GroundTemp));
    4576             :                         }
    4577           1 :                         state.dataSurfaceGeometry->NoGroundTempObjWarning = false;
    4578             :                     }
    4579             : 
    4580           0 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
    4581           0 :                     if (state.dataSurfaceGeometry->NoFCGroundTempObjWarning) {
    4582           0 :                         if (!state.dataEnvrn->FCGroundTemps) {
    4583           0 :                             ShowSevereError(state,
    4584             :                                             "GetRectSurfaces: Surfaces with interface to GroundFCfactorMethod found but no \"FC Ground "
    4585             :                                             "Temperatures\" were input.");
    4586           0 :                             ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
    4587           0 :                             ShowContinueError(state,
    4588             :                                               "Either add a \"Site:GroundTemperature:FCfactorMethod\" object or use a weather file with "
    4589             :                                               "Ground Temperatures.");
    4590           0 :                             ErrorsFound = true;
    4591           0 :                             state.dataSurfaceGeometry->NoFCGroundTempObjWarning = false;
    4592             :                         }
    4593             :                     }
    4594             : 
    4595             :                 } // ... End of the ExtBoundCond logical IF Block
    4596             : 
    4597         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataIPShortCut->rNumericArgs(1);
    4598         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataIPShortCut->rNumericArgs(2);
    4599         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    4600         119 :                     ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    4601         119 :                 if (!state.dataSurface->WorldCoordSystem) {
    4602          95 :                     if (ZoneNum != 0) {
    4603          95 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth +=
    4604          95 :                             state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->Zone(ZoneNum).RelNorth;
    4605             :                     }
    4606             :                 }
    4607         119 :                 if (ZoneNum != 0) {
    4608         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingRotationAppendixG;
    4609             :                 }
    4610             : 
    4611         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    4612         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4613             : 
    4614         714 :                 MakeRectangularVertices(state,
    4615             :                                         SurfNum,
    4616         119 :                                         state.dataIPShortCut->rNumericArgs(3),
    4617         119 :                                         state.dataIPShortCut->rNumericArgs(4),
    4618         119 :                                         state.dataIPShortCut->rNumericArgs(5),
    4619         119 :                                         state.dataIPShortCut->rNumericArgs(6),
    4620         119 :                                         state.dataIPShortCut->rNumericArgs(7),
    4621         119 :                                         state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem);
    4622             : 
    4623         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    4624           0 :                     ShowSevereError(state,
    4625           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    4626             :                                            cCurrentModuleObject,
    4627           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4628           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4629           0 :                     ErrorsFound = true;
    4630             :                 }
    4631             : 
    4632             :                 // Check wall height for the CFactor walls
    4633         198 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    4634          79 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
    4635           0 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height -
    4636           0 :                                  state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Height) > 0.05) {
    4637           0 :                         ShowWarningError(state,
    4638           0 :                                          format("{}=\"{}\", underground Wall Height = {:.2T}",
    4639             :                                                 cCurrentModuleObject,
    4640           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4641           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height));
    4642           0 :                         ShowContinueError(state, "..which deos not match its construction height.");
    4643             :                     }
    4644             :                 }
    4645             : 
    4646             :                 // Check area and perimeter for the FFactor floors
    4647         139 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    4648          20 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
    4649           0 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area -
    4650           0 :                                  state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Area) > 0.1) {
    4651           0 :                         ShowWarningError(state,
    4652           0 :                                          format("{}=\"{}\", underground Floor Area = {:.2T}",
    4653             :                                                 cCurrentModuleObject,
    4654           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4655           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4656           0 :                         ShowContinueError(state, "..which does not match its construction area.");
    4657             :                     }
    4658           0 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter <
    4659           0 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).PerimeterExposed - 0.1) {
    4660           0 :                         ShowWarningError(state,
    4661           0 :                                          format("{}=\"{}\", underground Floor Perimeter = {:.2T}",
    4662             :                                                 cCurrentModuleObject,
    4663           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4664           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter));
    4665           0 :                         ShowContinueError(state, "..which is less than its construction exposed perimeter.");
    4666             :                     }
    4667             :                 }
    4668             :             } // Getting Items
    4669             :         }
    4670         771 :     }
    4671             : 
    4672         139 :     void MakeRectangularVertices(EnergyPlusData &state,
    4673             :                                  int const SurfNum,
    4674             :                                  Real64 const XCoord,
    4675             :                                  Real64 const YCoord,
    4676             :                                  Real64 const ZCoord,
    4677             :                                  Real64 const Length,
    4678             :                                  Real64 const Height,
    4679             :                                  bool const SurfWorldCoordSystem)
    4680             :     {
    4681             : 
    4682             :         // SUBROUTINE INFORMATION:
    4683             :         //       AUTHOR         Linda Lawrie
    4684             :         //       DATE WRITTEN   December 2008
    4685             :         //       MODIFIED       na
    4686             :         //       RE-ENGINEERED  na
    4687             : 
    4688             :         // PURPOSE OF THIS SUBROUTINE:
    4689             :         // This routine creates world/3d coordinates for rectangular surfaces using azimuth, tilt, LLC (X,Y,Z), length & height.
    4690             : 
    4691             :         // METHODOLOGY EMPLOYED:
    4692             :         // na
    4693             : 
    4694             :         // REFERENCES:
    4695             :         // na
    4696             : 
    4697             :         // Using/Aliasing
    4698             :         using namespace Vectors;
    4699             : 
    4700             :         // Locals
    4701             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    4702             : 
    4703             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4704             :         // na
    4705             : 
    4706             :         // INTERFACE BLOCK SPECIFICATIONS:
    4707             :         // na
    4708             : 
    4709             :         // DERIVED TYPE DEFINITIONS:
    4710             :         // na
    4711             : 
    4712             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4713             :         Real64 SurfAzimuth; // Surface Azimuth/Facing (same as Base Surface)
    4714             :         Real64 SurfTilt;    // Tilt (same as Base Surface)
    4715             :         Real64 XLLC;
    4716             :         Real64 YLLC;
    4717             :         Real64 ZLLC;
    4718             :         Real64 CosSurfAzimuth;
    4719             :         Real64 SinSurfAzimuth;
    4720             :         Real64 CosSurfTilt;
    4721             :         Real64 SinSurfTilt;
    4722         278 :         Array1D<Real64> XX(4);
    4723         278 :         Array1D<Real64> YY(4);
    4724             :         Real64 Xb;
    4725             :         Real64 Yb;
    4726             :         Real64 Perimeter;
    4727             :         int n;
    4728             :         int Vrt;
    4729             : 
    4730         159 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone == 0 &&
    4731          26 :             (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F &&
    4732           6 :              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_B))
    4733           0 :             return;
    4734             : 
    4735         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = Height;
    4736         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = Length;
    4737             : 
    4738         139 :         SurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
    4739         139 :         SurfTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
    4740         139 :         CosSurfAzimuth = std::cos(SurfAzimuth * DataGlobalConstants::DegToRadians);
    4741         139 :         SinSurfAzimuth = std::sin(SurfAzimuth * DataGlobalConstants::DegToRadians);
    4742         139 :         CosSurfTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
    4743         139 :         SinSurfTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
    4744         139 :         if (!SurfWorldCoordSystem) {
    4745         111 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone > 0) {
    4746         285 :                 Xb = XCoord * state.dataSurfaceGeometry->CosZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) -
    4747          95 :                      YCoord * state.dataSurfaceGeometry->SinZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
    4748          95 :                      state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginX;
    4749         285 :                 Yb = XCoord * state.dataSurfaceGeometry->SinZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
    4750          95 :                      YCoord * state.dataSurfaceGeometry->CosZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
    4751          95 :                      state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginY;
    4752          95 :                 XLLC = Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    4753          95 :                 YLLC = Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    4754          95 :                 ZLLC = ZCoord + state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginZ;
    4755             :             } else {
    4756          16 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    4757           5 :                     Xb = XCoord;
    4758           5 :                     Yb = YCoord;
    4759           5 :                     XLLC = Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    4760           5 :                     YLLC = Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    4761           5 :                     ZLLC = ZCoord;
    4762             :                 } else {
    4763          11 :                     XLLC = XCoord;
    4764          11 :                     YLLC = YCoord;
    4765          11 :                     ZLLC = ZCoord;
    4766             :                 }
    4767             :             }
    4768             :         } else {
    4769             :             // for world coordinates, only rotate for appendix G
    4770          28 :             Xb = XCoord;
    4771          28 :             Yb = YCoord;
    4772          28 :             ZLLC = ZCoord;
    4773          28 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F) {
    4774          25 :                 XLLC = Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
    4775          25 :                 YLLC = Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
    4776             :             } else {
    4777           3 :                 XLLC = Xb;
    4778           3 :                 YLLC = Yb;
    4779             :             }
    4780             :         }
    4781             : 
    4782         139 :         XX(1) = 0.0;
    4783         139 :         XX(2) = 0.0;
    4784         139 :         XX(3) = Length;
    4785         139 :         XX(4) = Length;
    4786         139 :         YY(1) = Height;
    4787         139 :         YY(4) = Height;
    4788         139 :         YY(3) = 0.0;
    4789         139 :         YY(2) = 0.0;
    4790             : 
    4791         695 :         for (n = 1; n <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++n) {
    4792         556 :             Vrt = n;
    4793         556 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).x = XLLC - XX(n) * CosSurfAzimuth - YY(n) * CosSurfTilt * SinSurfAzimuth;
    4794         556 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).y = YLLC + XX(n) * SinSurfAzimuth - YY(n) * CosSurfTilt * CosSurfAzimuth;
    4795         556 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).z = ZLLC + YY(n) * SinSurfTilt;
    4796             :         }
    4797             : 
    4798         278 :         CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    4799         139 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4800         139 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    4801         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    4802         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    4803         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    4804         278 :         CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    4805         139 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4806         139 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    4807         834 :         DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    4808         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4809             :                                 SurfAzimuth,
    4810             :                                 SurfTilt,
    4811         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    4812         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    4813         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    4814         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
    4815         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    4816         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfAzimuth;
    4817         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    4818         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    4819         139 :             ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    4820             :         // Sine and cosine of azimuth and tilt
    4821         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = SinSurfAzimuth;
    4822         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = CosSurfAzimuth;
    4823         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = SinSurfTilt;
    4824         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = CosSurfTilt;
    4825         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    4826             :         // Outward normal unit vector (pointing away from room)
    4827         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    4828         556 :         for (n = 1; n <= 3; ++n) {
    4829         417 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    4830          71 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    4831         417 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    4832          68 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    4833         417 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    4834         278 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    4835             :         }
    4836             : 
    4837             :         // Can perform tests on this surface here
    4838         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    4839             :         // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    4840             :         // surfaces
    4841         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    4842         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    4843             : 
    4844         139 :         Perimeter = distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides),
    4845         139 :                              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1));
    4846         556 :         for (Vrt = 2; Vrt <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vrt) {
    4847         417 :             Perimeter +=
    4848         834 :                 distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt), state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt - 1));
    4849             :         }
    4850         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
    4851             : 
    4852             :         // Call to transform vertices
    4853             : 
    4854         139 :         TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4855             :     }
    4856             : 
    4857         771 :     void GetHTSubSurfaceData(EnergyPlusData &state,
    4858             :                              bool &ErrorsFound,                       // Error flag indicator (true if errors found)
    4859             :                              int &SurfNum,                            // Count of Current SurfaceNumber
    4860             :                              int const TotHTSubs,                     // Number of Heat Transfer SubSurfaces to obtain
    4861             :                              const Array1D_string &SubSurfCls,        // Valid Classes for Sub Surfaces
    4862             :                              const Array1D<SurfaceClass> &SubSurfIDs, // ID Assignments for valid sub surface classes
    4863             :                              int &AddedSubSurfaces,                   // Subsurfaces added when windows reference Window5
    4864             :                              int &NeedToAddSurfaces                   // Number of surfaces to add, based on unentered IZ surfaces
    4865             :     )
    4866             :     {
    4867             : 
    4868             :         // SUBROUTINE INFORMATION:
    4869             :         //       AUTHOR         Linda Lawrie
    4870             :         //       DATE WRITTEN   May 2000
    4871             :         //       MODIFIED       August 2012 - line up subsurfaces with base surface types
    4872             :         //       RE-ENGINEERED  na
    4873             : 
    4874             :         // PURPOSE OF THIS SUBROUTINE:
    4875             :         // This subroutine gets the HeatTransfer Sub Surface Data,
    4876             :         // checks it for errors, etc.
    4877             : 
    4878             :         // METHODOLOGY EMPLOYED:
    4879             :         // na
    4880             : 
    4881             :         // REFERENCES:
    4882             :         // Heat Transfer Subsurface Definition
    4883             :         // FenestrationSurface:Detailed,
    4884             :         //        \min-fields 19
    4885             :         //        \memo Used for windows, doors, glass doors, tubular daylighting devices
    4886             :         //        \format vertices
    4887             :         //   A1 , \field Name
    4888             :         //        \required-field
    4889             :         //        \type alpha
    4890             :         //   A2 , \field Surface Type
    4891             :         //        \required-field
    4892             :         //        \type choice
    4893             :         //        \key Window
    4894             :         //        \key Door
    4895             :         //        \key GlassDoor
    4896             :         //        \key TubularDaylightDome
    4897             :         //        \key TubularDaylightDiffuser
    4898             :         //   A3 , \field Construction Name
    4899             :         //        \required-field
    4900             :         //        \note To be matched with a construction in this input file
    4901             :         //        \type object-list
    4902             :         //        \object-list ConstructionNames
    4903             :         //   A4 , \field Building Surface Name
    4904             :         //        \required-field
    4905             :         //        \type object-list
    4906             :         //        \object-list SurfaceNames
    4907             :         //   A5,  \field Outside Boundary Condition Object
    4908             :         //        \type object-list
    4909             :         //        \object-list OutFaceEnvNames
    4910             :         //        \note Non-blank only if base surface field Outside Boundary Condition is
    4911             :         //        \note Surface or OtherSideCoefficients
    4912             :         //        \note If Base Surface's Surface, specify name of corresponding subsurface in adjacent zone or
    4913             :         //        \note specify current subsurface name for internal partition separating like zones
    4914             :         //        \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
    4915             :         //        \note  or leave blank to inherit Base Surface's OtherSide Coefficients
    4916             :         //   N1, \field View Factor to Ground
    4917             :         //        \type real
    4918             :         //        \note From the exterior of the surface
    4919             :         //        \note Unused if one uses the "reflections" options in Solar Distribution in Building input
    4920             :         //        \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
    4921             :         //        \note autocalculate will automatically calculate this value from the tilt of the surface
    4922             :         //        \autocalculatable
    4923             :         //        \minimum 0.0
    4924             :         //        \maximum 1.0
    4925             :         //        \default autocalculate
    4926             :         //   A6, \field Frame and Divider Name
    4927             :         //        \note Enter the name of a WindowProperty:FrameAndDivider object
    4928             :         //        \type object-list
    4929             :         //        \object-list WindowFrameAndDividerNames
    4930             :         //        \note Used only for exterior windows (rectangular) and glass doors.
    4931             :         //        \note Unused for triangular windows.
    4932             :         //        \note If not specified (blank), window or glass door has no frame or divider
    4933             :         //        \note and no beam solar reflection from reveal surfaces.
    4934             :         //   N2 , \field Multiplier
    4935             :         //        \note Used only for Surface Type = WINDOW, GLASSDOOR or DOOR
    4936             :         //        \note Non-integer values will be truncated to integer
    4937             :         //        \default 1.0
    4938             :         //        \minimum 1.0
    4939             :         //   N3 , \field Number of Vertices
    4940             :         //        \minimum 3
    4941             :         //        \maximum 4
    4942             :         //        \autocalculatable
    4943             :         //        \default autocalculate
    4944             :         //        \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
    4945             :         //        \note are "relative" to the Zone Origin.  If world, then building and zone origins are used
    4946             :         //        \note for some internal calculations, but all coordinates are given in an "absolute" system.
    4947             :         //  N4-15 as indicated by the N3 value
    4948             : 
    4949             :         // Using/Aliasing
    4950             : 
    4951             :         // Locals
    4952             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    4953             :         //  data file entry with two glazing systems
    4954             : 
    4955             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4956             :         int IOStat;          // IO Status when calling get input subroutine
    4957             :         int SurfaceNumAlpha; // Number of material alpha names being passed
    4958             :         int SurfaceNumProp;  // Number of material properties being passed
    4959             :         int Found;           // For matching interzone surfaces
    4960             :         int Loop;
    4961             :         int ValidChk;
    4962             :         int numSides;
    4963             : 
    4964         771 :         GetWindowShadingControlData(state, ErrorsFound);
    4965         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    4966         771 :         cCurrentModuleObject = "FenestrationSurface:Detailed";
    4967         771 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, SurfaceNumAlpha, SurfaceNumProp);
    4968             : 
    4969         771 :         if (SurfaceNumAlpha != 6) {
    4970           0 :             ShowSevereError(
    4971           0 :                 state, format("{}: Object Definition indicates not = 6 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    4972           0 :             ErrorsFound = true;
    4973             :         }
    4974             : 
    4975         771 :         if (SurfaceNumProp != 15) {
    4976           0 :             ShowSevereError(
    4977           0 :                 state, format("{}: Object Definition indicates > 15 Numeric Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    4978           0 :             ErrorsFound = true;
    4979             :         }
    4980         771 :         NeedToAddSurfaces = 0;
    4981             : 
    4982        7144 :         for (Loop = 1; Loop <= TotHTSubs; ++Loop) {
    4983       44611 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4984             :                                                                      cCurrentModuleObject,
    4985             :                                                                      Loop,
    4986        6373 :                                                                      state.dataIPShortCut->cAlphaArgs,
    4987             :                                                                      SurfaceNumAlpha,
    4988        6373 :                                                                      state.dataIPShortCut->rNumericArgs,
    4989             :                                                                      SurfaceNumProp,
    4990             :                                                                      IOStat,
    4991        6373 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    4992        6373 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    4993        6373 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    4994        6373 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    4995             : 
    4996       12746 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    4997        6373 :                                                          state.dataSurfaceGeometry->UniqueSurfaceNames,
    4998        6373 :                                                          state.dataIPShortCut->cAlphaArgs(1),
    4999             :                                                          cCurrentModuleObject,
    5000        6373 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    5001             :                                                          ErrorsFound)) {
    5002           0 :                 continue;
    5003             :             }
    5004             : 
    5005        6373 :             if (SurfaceNumProp < 12) {
    5006           0 :                 ShowSevereError(state,
    5007           0 :                                 format("{}=\"{}\", Too few number of numeric args=[{}].",
    5008             :                                        cCurrentModuleObject,
    5009           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5010           0 :                                        SurfaceNumProp));
    5011           0 :                 ErrorsFound = true;
    5012             :             }
    5013             : 
    5014        6373 :             ++SurfNum;
    5015        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    5016        6373 :             ValidChk = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), SubSurfCls, 6);
    5017        6373 :             if (ValidChk == 0) {
    5018           0 :                 ShowSevereError(state,
    5019           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5020           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    5021           0 :                 ErrorsFound = true;
    5022             :             } else {
    5023        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SubSurfIDs(ValidChk); // Set class number
    5024             :             }
    5025             : 
    5026       19119 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
    5027       19119 :                 state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    5028             : 
    5029        6373 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    5030           0 :                 ShowSevereError(state,
    5031           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5032           0 :                                     state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
    5033           0 :                 ErrorsFound = true;
    5034           0 :                 continue;
    5035             :             } else {
    5036        6373 :                 state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    5037        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    5038        6373 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    5039             :             }
    5040             : 
    5041       13710 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5042        1424 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5043        7291 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser ||
    5044         458 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome) {
    5045             : 
    5046        5917 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5047        5917 :                     auto &construction = state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction);
    5048        5917 :                     if (!construction.TypeIsWindow && !construction.TypeIsAirBoundary) {
    5049           0 :                         ErrorsFound = true;
    5050           0 :                         ShowSevereError(state,
    5051           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5052             :                                             "\" has an opaque surface construction; it should have a window construction.");
    5053             :                     }
    5054        5917 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
    5055           0 :                         ErrorsFound = true;
    5056           0 :                         ShowSevereError(state,
    5057           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5058             :                                             "\": Windows are not allowed to have embedded sources/sinks");
    5059             :                     }
    5060             :                 }
    5061             : 
    5062         456 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5063         456 :                 if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    5064           0 :                     ErrorsFound = true;
    5065           0 :                     ShowSevereError(state,
    5066           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5067           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    5068             :                                         "\" - has Window materials.");
    5069           0 :                     ShowContinueError(state, "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
    5070             :                 }
    5071             :             }
    5072             : 
    5073        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    5074             : 
    5075        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(4);
    5076             :             //  The subsurface inherits properties from the base surface
    5077             :             //  Exterior conditions, Zone, etc.
    5078             :             //  We can figure out the base surface though, because they've all been entered
    5079       19119 :             Found = UtilityRoutines::FindItemInList(
    5080       19119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
    5081        6373 :             if (Found > 0) {
    5082        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
    5083        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    5084        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName;
    5085        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    5086        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    5087        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
    5088        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
    5089        6373 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
    5090        6437 :                 if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface &&
    5091          64 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName ==
    5092          64 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed
    5093           0 :                     ShowSevereError(state,
    5094           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5095           0 :                                         state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
    5096           0 :                     ShowContinueError(state, "... adiabatic surfaces cannot have windows or doors.");
    5097           0 :                     ShowContinueError(state,
    5098             :                                       "... no solar transmission will result for these windows or doors. You must have interior windows or doors on "
    5099             :                                       "Interzone surfaces for transmission to result.");
    5100             :                 }
    5101             :             } else {
    5102           0 :                 ShowSevereError(state,
    5103           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5104           0 :                                     state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4));
    5105           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    5106           0 :                 ErrorsFound = true;
    5107             :             }
    5108       12744 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome ||
    5109        6371 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser) {
    5110           4 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    5111             :             }
    5112             : 
    5113        6373 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
    5114        6294 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    5115           0 :                     ShowWarningError(state,
    5116           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid field " +
    5117           0 :                                          state.dataIPShortCut->cAlphaFieldNames(5));
    5118           0 :                     ShowContinueError(state,
    5119           0 :                                       "...when Base surface uses \"Outdoors\" as " + state.dataIPShortCut->cAlphaFieldNames(5) +
    5120             :                                           ", subsurfaces need to be blank to inherit the outdoor characteristics.");
    5121           0 :                     ShowContinueError(state, "...Surface external characteristics changed to reflect base surface.");
    5122             :                 }
    5123             :             }
    5124             : 
    5125        6373 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
    5126          62 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    5127          62 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(5);
    5128             :                 } else {
    5129           0 :                     ShowSevereError(state,
    5130           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid blank " +
    5131           0 :                                         state.dataIPShortCut->cAlphaFieldNames(5));
    5132           0 :                     ShowContinueError(state,
    5133           0 :                                       "...when Base surface uses \"Surface\" as " + state.dataIPShortCut->cAlphaFieldNames(5) +
    5134             :                                           ", subsurfaces must also specify specific surfaces in the adjacent zone.");
    5135           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5136           0 :                         state.dataIPShortCut->cAlphaArgs(5); // putting it as blank will not confuse things later.
    5137           0 :                     ErrorsFound = true;
    5138             :                 }
    5139             :             }
    5140             : 
    5141        6373 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface
    5142           1 :                 ++NeedToAddSurfaces;
    5143             :                 // ignoring window5datafiles for now -- will need to add.
    5144             :             }
    5145             : 
    5146       12730 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
    5147        6357 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
    5148          16 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { // Otherside Coef special Name
    5149           2 :                     Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(5), state.dataSurface->OSC, state.dataSurface->TotOSC);
    5150           2 :                     if (Found == 0) {
    5151           0 :                         ShowSevereError(state,
    5152           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5153           0 :                                             state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\".");
    5154           0 :                         ShowContinueError(state, "...base surface requires that this subsurface have OtherSideCoefficients -- not found.");
    5155           0 :                         ErrorsFound = true;
    5156             :                     } else { // found
    5157             :                         // The following allows for a subsurface that has different characteristics than
    5158             :                         // the base surface with OtherSide Coeff -- do we want that or is it an error?
    5159           2 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
    5160           2 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(5);
    5161           2 :                         if (state.dataSurface->OSC(Found).SurfFilmCoef > 0.0) {
    5162           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefCalcExt;
    5163             :                         } else {
    5164           2 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefNoCalcExt;
    5165             :                         }
    5166             :                     }
    5167             :                 }
    5168             :             }
    5169             : 
    5170        6373 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCondModeledExt) {
    5171           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    5172             :             }
    5173             : 
    5174        6373 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName == BlankString) {
    5175        6284 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    5176             :             }
    5177        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataIPShortCut->rNumericArgs(1);
    5178        6373 :             if (state.dataIPShortCut->lNumericFieldBlanks(1))
    5179         355 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = DataGlobalConstants::AutoCalculate;
    5180             : 
    5181        6373 :             if (state.dataIPShortCut->lNumericFieldBlanks(3) || state.dataIPShortCut->rNumericArgs(3) == DataGlobalConstants::AutoCalculate) {
    5182          53 :                 state.dataIPShortCut->rNumericArgs(3) = (SurfaceNumProp - 3) / 3;
    5183          53 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(3);
    5184          53 :                 if (mod(SurfaceNumProp - 3, 3) != 0) {
    5185           0 :                     ShowWarningError(state,
    5186           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    5187           0 :                                          format("{} not even multiple of 3. Will read in {}",
    5188           0 :                                                 state.dataIPShortCut->cNumericFieldNames(3),
    5189           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    5190             :                 }
    5191          53 :                 if (state.dataIPShortCut->rNumericArgs(3) < 3) {
    5192           0 :                     ShowSevereError(state,
    5193           0 :                                     format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    5194             :                                            cCurrentModuleObject,
    5195           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5196           0 :                                            state.dataIPShortCut->cNumericFieldNames(3),
    5197           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    5198           0 :                     ErrorsFound = true;
    5199           0 :                     continue;
    5200             :                 }
    5201             :             } else {
    5202        6320 :                 numSides = (SurfaceNumProp - 2) / 3;
    5203        6320 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(3);
    5204        6320 :                 if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
    5205           0 :                     ShowWarningError(state,
    5206           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", field " +
    5207           0 :                                          state.dataIPShortCut->cNumericFieldNames(3) + '=' +
    5208           0 :                                          fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    5209           0 :                     ShowContinueError(
    5210             :                         state,
    5211           0 :                         format("...but {} were entered. Only the indicated {} will be used.", numSides, state.dataIPShortCut->cNumericFieldNames(3)));
    5212             :                 }
    5213             :             }
    5214        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    5215       13710 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5216        6833 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5217         460 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    5218        6369 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = int(state.dataIPShortCut->rNumericArgs(2));
    5219             :             // Only windows, glass doors and doors can have Multiplier > 1:
    5220       13710 :             if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
    5221        1424 :                  state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
    5222        6837 :                  state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door) &&
    5223           4 :                 state.dataIPShortCut->rNumericArgs(2) > 1.0) {
    5224           0 :                 ShowWarningError(state,
    5225           0 :                                  format("{}=\"{}\", invalid {}=[{:.1T}].",
    5226             :                                         cCurrentModuleObject,
    5227           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5228           0 :                                         state.dataIPShortCut->cNumericFieldNames(2),
    5229           0 :                                         state.dataIPShortCut->rNumericArgs(2)));
    5230           0 :                 ShowContinueError(state,
    5231           0 :                                   "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2) +
    5232             :                                       " multiplier will be set to 1.0.");
    5233           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = 1.0;
    5234             :             }
    5235             : 
    5236        6373 :             GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({4, _}));
    5237             : 
    5238        6373 :             CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    5239        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.clear();
    5240        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
    5241        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = false;
    5242             : 
    5243        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.clear();
    5244        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = 0;
    5245        6373 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList.clear();
    5246             : 
    5247       13710 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5248        1424 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5249        7291 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser ||
    5250         458 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome) {
    5251             : 
    5252       11834 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
    5253        5917 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
    5254           0 :                     ShowSevereError(state,
    5255           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5256             :                                         "\", Other side coefficients are not allowed with windows.");
    5257           0 :                     ErrorsFound = true;
    5258             :                 }
    5259             : 
    5260        5917 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    5261           0 :                     ShowSevereError(state,
    5262           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5263             :                                         "\", Exterior boundary condition = Ground is not allowed with windows.");
    5264           0 :                     ErrorsFound = true;
    5265             :                 }
    5266             : 
    5267        5917 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == KivaFoundation) {
    5268           0 :                     ShowSevereError(state,
    5269           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5270             :                                         "\", Exterior boundary condition = Foundation is not allowed with windows.");
    5271           0 :                     ErrorsFound = true;
    5272             :                 }
    5273             : 
    5274        5917 :                 InitialAssociateWindowShadingControlFenestration(state, ErrorsFound, SurfNum);
    5275             : 
    5276        5917 :                 CheckWindowShadingControlFrameDivider(state, "GetHTSubSurfaceData", ErrorsFound, SurfNum, 6);
    5277             : 
    5278        5917 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides == 3) { // Triangular window
    5279           2 :                     if (!state.dataIPShortCut->cAlphaArgs(6).empty()) {
    5280           0 :                         ShowWarningError(state,
    5281           0 :                                          cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5282           0 :                                              state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" + state.dataIPShortCut->cAlphaArgs(6) + "\".");
    5283           0 :                         ShowContinueError(state, ".. because it is a triangular window and cannot have a frame or divider or reveal reflection.");
    5284           0 :                         ShowContinueError(state, "Frame, divider and reveal reflection will be ignored for this window.");
    5285             :                     }
    5286           2 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider = 0;
    5287             :                 } // End of check if window is triangular or rectangular
    5288             : 
    5289             :             } // check on non-opaquedoor subsurfaces
    5290             : 
    5291       12746 :             CheckSubSurfaceMiscellaneous(state,
    5292             :                                          "GetHTSubSurfaceData",
    5293             :                                          ErrorsFound,
    5294             :                                          SurfNum,
    5295        6373 :                                          state.dataIPShortCut->cAlphaArgs(1),
    5296        6373 :                                          state.dataIPShortCut->cAlphaArgs(3),
    5297        6373 :                                          AddedSubSurfaces);
    5298             : 
    5299             :         } // End of main loop over subsurfaces
    5300         771 :     }
    5301             : 
    5302         771 :     void GetRectSubSurfaces(EnergyPlusData &state,
    5303             :                             bool &ErrorsFound,                       // Error flag indicator (true if errors found)
    5304             :                             int &SurfNum,                            // Count of Current SurfaceNumber
    5305             :                             int const TotWindows,                    // Number of Window SubSurfaces to obtain
    5306             :                             int const TotDoors,                      // Number of Door SubSurfaces to obtain
    5307             :                             int const TotGlazedDoors,                // Number of Glass Door SubSurfaces to obtain
    5308             :                             int const TotIZWindows,                  // Number of Interzone Window SubSurfaces to obtain
    5309             :                             int const TotIZDoors,                    // Number of Interzone Door SubSurfaces to obtain
    5310             :                             int const TotIZGlazedDoors,              // Number of Interzone Glass Door SubSurfaces to obtain
    5311             :                             const Array1D<SurfaceClass> &SubSurfIDs, // ID Assignments for valid sub surface classes
    5312             :                             int &AddedSubSurfaces,                   // Subsurfaces added when windows reference Window5
    5313             :                             int &NeedToAddSubSurfaces                // Number of surfaces to add, based on unentered IZ surfaces
    5314             :     )
    5315             :     {
    5316             : 
    5317             :         // SUBROUTINE INFORMATION:
    5318             :         //       AUTHOR         Linda Lawrie
    5319             :         //       DATE WRITTEN   December 2008
    5320             :         //       MODIFIED       na
    5321             :         //       RE-ENGINEERED  na
    5322             : 
    5323             :         // PURPOSE OF THIS SUBROUTINE:
    5324             :         // Get simple (rectangular, relative origin to base surface) windows, doors, glazed doors.
    5325             : 
    5326             :         // Using/Aliasing
    5327             : 
    5328             :         // Locals
    5329             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    5330             :         //  data file entry with two glazing systems
    5331             : 
    5332             :         // SUBROUTINE PARAMETER DEFINITIONS:
    5333         771 :         static Array1D_string const cModuleObjects(6, {"Window", "Door", "GlazedDoor", "Window:Interzone", "Door:Interzone", "GlazedDoor:Interzone"});
    5334             : 
    5335             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5336             :         int Item;
    5337             :         int ItemsToGet;
    5338             :         int Loop;
    5339             :         int NumAlphas;
    5340             :         int NumNumbers;
    5341             :         int IOStat; // IO Status when calling get input subroutine
    5342             :         int Found;  // For matching base surfaces
    5343             :         bool GettingIZSurfaces;
    5344             :         int WindowShadingField;
    5345             :         int FrameField;
    5346             :         int OtherSurfaceField;
    5347             :         int ClassItem;
    5348             :         int IZFound;
    5349         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    5350        5397 :         for (Item = 1; Item <= 6; ++Item) {
    5351             : 
    5352        4626 :             cCurrentModuleObject = cModuleObjects(Item);
    5353        4626 :             if (Item == 1) {
    5354         771 :                 ItemsToGet = TotWindows;
    5355         771 :                 GettingIZSurfaces = false;
    5356         771 :                 WindowShadingField = 4;
    5357         771 :                 FrameField = 5;
    5358         771 :                 OtherSurfaceField = 0;
    5359         771 :                 ClassItem = 1;
    5360        3855 :             } else if (Item == 2) {
    5361         771 :                 ItemsToGet = TotDoors;
    5362         771 :                 GettingIZSurfaces = false;
    5363         771 :                 WindowShadingField = 0;
    5364         771 :                 FrameField = 0;
    5365         771 :                 OtherSurfaceField = 0;
    5366         771 :                 ClassItem = 2;
    5367        3084 :             } else if (Item == 3) {
    5368         771 :                 ItemsToGet = TotGlazedDoors;
    5369         771 :                 GettingIZSurfaces = false;
    5370         771 :                 WindowShadingField = 4;
    5371         771 :                 FrameField = 5;
    5372         771 :                 OtherSurfaceField = 0;
    5373         771 :                 ClassItem = 3;
    5374        2313 :             } else if (Item == 4) {
    5375         771 :                 ItemsToGet = TotIZWindows;
    5376         771 :                 GettingIZSurfaces = true;
    5377         771 :                 WindowShadingField = 0;
    5378         771 :                 FrameField = 0;
    5379         771 :                 OtherSurfaceField = 4;
    5380         771 :                 ClassItem = 1;
    5381        1542 :             } else if (Item == 5) {
    5382         771 :                 ItemsToGet = TotIZDoors;
    5383         771 :                 GettingIZSurfaces = true;
    5384         771 :                 WindowShadingField = 0;
    5385         771 :                 FrameField = 0;
    5386         771 :                 OtherSurfaceField = 4;
    5387         771 :                 ClassItem = 2;
    5388             :             } else { // Item = 6
    5389         771 :                 ItemsToGet = TotIZGlazedDoors;
    5390         771 :                 GettingIZSurfaces = true;
    5391         771 :                 WindowShadingField = 0;
    5392         771 :                 FrameField = 0;
    5393         771 :                 OtherSurfaceField = 4;
    5394         771 :                 ClassItem = 3;
    5395             :             }
    5396             : 
    5397        4691 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    5398         455 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5399             :                                                                          cCurrentModuleObject,
    5400             :                                                                          Loop,
    5401          65 :                                                                          state.dataIPShortCut->cAlphaArgs,
    5402             :                                                                          NumAlphas,
    5403          65 :                                                                          state.dataIPShortCut->rNumericArgs,
    5404             :                                                                          NumNumbers,
    5405             :                                                                          IOStat,
    5406          65 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    5407          65 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    5408          65 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    5409          65 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    5410             : 
    5411         130 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    5412          65 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    5413          65 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    5414             :                                                              cCurrentModuleObject,
    5415          65 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    5416             :                                                              ErrorsFound)) {
    5417           0 :                     continue;
    5418             :                 }
    5419             : 
    5420          65 :                 if (NumNumbers < 5) {
    5421           0 :                     ShowSevereError(state,
    5422           0 :                                     format("{}=\"{}\", Too few number of numeric args=[{}].",
    5423             :                                            cCurrentModuleObject,
    5424           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    5425           0 :                                            NumNumbers));
    5426           0 :                     ErrorsFound = true;
    5427             :                 }
    5428             : 
    5429          65 :                 ++SurfNum;
    5430          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    5431          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SubSurfIDs(ClassItem);              // Set class number
    5432             : 
    5433         195 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
    5434         195 :                     state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    5435             : 
    5436          65 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    5437           0 :                     ErrorsFound = true;
    5438           0 :                     ShowSevereError(state,
    5439           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5440           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
    5441             :                 } else {
    5442          65 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    5443          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    5444          65 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    5445             :                 }
    5446             : 
    5447          75 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5448          10 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) {
    5449             : 
    5450          57 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5451          57 :                         auto &construction = state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction);
    5452          57 :                         if (!construction.TypeIsWindow && !construction.TypeIsAirBoundary) {
    5453           0 :                             ErrorsFound = true;
    5454           0 :                             ShowSevereError(state,
    5455           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5456             :                                                 "\" has an opaque surface construction; it should have a window construction.");
    5457             :                         }
    5458          57 :                         if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
    5459           0 :                             ErrorsFound = true;
    5460           0 :                             ShowSevereError(state,
    5461           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5462             :                                                 "\": Windows are not allowed to have embedded sources/sinks");
    5463             :                         }
    5464             :                     }
    5465             : 
    5466           8 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5467           8 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    5468           0 :                         ErrorsFound = true;
    5469           0 :                         ShowSevereError(state,
    5470           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5471           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    5472             :                                             "\" - has Window materials.");
    5473             :                     }
    5474             :                 }
    5475             : 
    5476          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    5477             : 
    5478          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(3);
    5479             :                 //  The subsurface inherits properties from the base surface
    5480             :                 //  Exterior conditions, Zone, etc.
    5481             :                 //  We can figure out the base surface though, because they've all been entered
    5482         130 :                 Found = UtilityRoutines::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    5483          65 :                                                         state.dataSurfaceGeometry->SurfaceTmp,
    5484          65 :                                                         state.dataSurface->TotSurfaces);
    5485          65 :                 if (Found > 0) {
    5486          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
    5487          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    5488          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName;
    5489          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    5490          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    5491          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
    5492          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    5493          65 :                         ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    5494          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth;
    5495          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
    5496          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
    5497          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
    5498          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataSurfaceGeometry->SurfaceTmp(Found).ViewFactorGround;
    5499          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = state.dataSurfaceGeometry->SurfaceTmp(Found).ViewFactorSky;
    5500             :                 } else {
    5501           0 :                     ShowSevereError(state,
    5502           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5503           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
    5504           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    5505           0 :                     ErrorsFound = true;
    5506           0 :                     continue;
    5507             :                 }
    5508          73 :                 if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface &&
    5509           8 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName ==
    5510           8 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed
    5511           0 :                     ShowSevereError(state,
    5512           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5513           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
    5514           0 :                     ShowContinueError(state, "... adiabatic surfaces cannot have windows or doors.");
    5515           0 :                     ShowContinueError(state,
    5516             :                                       "... no solar transmission will result for these windows or doors. You must have interior windows or doors on "
    5517             :                                       "Interzone surfaces for transmission to result.");
    5518             :                 }
    5519             : 
    5520          65 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
    5521           8 :                     if (!GettingIZSurfaces) {
    5522           0 :                         ShowSevereError(
    5523           0 :                             state, cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid use of object");
    5524           0 :                         ShowContinueError(state,
    5525           0 :                                           "...when Base surface uses \"Surface\" as " + state.dataIPShortCut->cAlphaFieldNames(5) +
    5526             :                                               ", subsurfaces must also specify specific surfaces in the adjacent zone.");
    5527           0 :                         ShowContinueError(state, "...Please use " + cCurrentModuleObject + ":Interzone to enter this surface.");
    5528           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5529           0 :                             BlankString; // putting it as blank will not confuse things later.
    5530           0 :                         ErrorsFound = true;
    5531             :                     }
    5532             :                 }
    5533             : 
    5534          65 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
    5535           8 :                     if (GettingIZSurfaces) {
    5536           8 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(OtherSurfaceField);
    5537          24 :                         IZFound = UtilityRoutines::FindItemInList(
    5538          24 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    5539           8 :                         if (IZFound > 0) state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    5540             :                     } else { // Interior Window
    5541           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    5542             :                     }
    5543             :                 }
    5544             : 
    5545             :                 // This is the parent's property:
    5546          65 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond ==
    5547             :                     UnenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface
    5548           3 :                     if (GettingIZSurfaces) {
    5549           3 :                         ++NeedToAddSubSurfaces;
    5550             :                     } else { // Interior Window
    5551           0 :                         ShowSevereError(state,
    5552           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5553           0 :                                             "\", invalid Interzone Surface, specify " + cCurrentModuleObject + ":InterZone");
    5554           0 :                         ShowContinueError(state, "...when base surface is an interzone surface, subsurface must also be an interzone surface.");
    5555           0 :                         ++NeedToAddSubSurfaces;
    5556           0 :                         ErrorsFound = true;
    5557             :                     }
    5558             :                 }
    5559             : 
    5560          65 :                 if (GettingIZSurfaces) {
    5561          11 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(OtherSurfaceField)) {
    5562             :                         // blank -- set it up for unentered adjacent zone
    5563           0 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond ==
    5564             :                             UnenteredAdjacentZoneSurface) { // already set but need Zone
    5565           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5566           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName; // base surface has it
    5567           0 :                         } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    5568           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5569           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // base surface has it
    5570           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    5571             :                         } else { // not correct boundary condition for interzone subsurface
    5572           0 :                             ShowSevereError(state,
    5573           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5574             :                                                 "\", invalid Base Surface type for Interzone Surface");
    5575           0 :                             ShowContinueError(state,
    5576             :                                               "...when base surface is not an interzone surface, subsurface must also not be an interzone surface.");
    5577           0 :                             ErrorsFound = true;
    5578             :                         }
    5579             :                     }
    5580             :                 }
    5581             : 
    5582          65 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCondModeledExt) {
    5583           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    5584             :                 }
    5585             : 
    5586             :                 //      SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate
    5587             : 
    5588          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    5589          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    5590         140 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5591          73 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5592           8 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    5593          65 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = int(state.dataIPShortCut->rNumericArgs(1));
    5594             :                 // Only windows, glass doors and doors can have Multiplier > 1:
    5595         140 :                 if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
    5596          18 :                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
    5597          73 :                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door) &&
    5598           0 :                     state.dataIPShortCut->rNumericArgs(1) > 1.0) {
    5599           0 :                     ShowWarningError(state,
    5600           0 :                                      format("{}=\"{}\", invalid {}=[{:.1T}].",
    5601             :                                             cCurrentModuleObject,
    5602           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5603           0 :                                             state.dataIPShortCut->cNumericFieldNames(1),
    5604           0 :                                             state.dataIPShortCut->rNumericArgs(1)));
    5605           0 :                     ShowContinueError(state,
    5606           0 :                                       "...because " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' + state.dataIPShortCut->cAlphaArgs(1) +
    5607             :                                           " multiplier will be set to 1.0.");
    5608           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = 1.0;
    5609             :                 }
    5610             : 
    5611         325 :                 MakeRelativeRectangularVertices(state,
    5612          65 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf,
    5613             :                                                 SurfNum,
    5614          65 :                                                 state.dataIPShortCut->rNumericArgs(2),
    5615          65 :                                                 state.dataIPShortCut->rNumericArgs(3),
    5616          65 :                                                 state.dataIPShortCut->rNumericArgs(4),
    5617          65 :                                                 state.dataIPShortCut->rNumericArgs(5));
    5618             : 
    5619          65 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    5620           0 :                     ShowSevereError(state,
    5621           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    5622             :                                            cCurrentModuleObject,
    5623           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5624           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    5625           0 :                     ErrorsFound = true;
    5626             :                 }
    5627             : 
    5628          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.clear();
    5629          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
    5630          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = false;
    5631             : 
    5632          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.clear();
    5633          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = 0;
    5634          65 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList.clear();
    5635             : 
    5636          65 :                 InitialAssociateWindowShadingControlFenestration(state, ErrorsFound, SurfNum);
    5637             : 
    5638          73 :                 if (!GettingIZSurfaces && (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5639           8 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor)) {
    5640             : 
    5641          94 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
    5642          47 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
    5643           0 :                         ShowSevereError(state,
    5644           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5645             :                                             "\", Other side coefficients are not allowed with windows.");
    5646           0 :                         ErrorsFound = true;
    5647             :                     }
    5648             : 
    5649          47 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    5650           0 :                         ShowSevereError(state,
    5651           0 :                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5652             :                                             "\", Exterior boundary condition = Ground is not allowed with windows.");
    5653           0 :                         ErrorsFound = true;
    5654             :                     }
    5655             : 
    5656          47 :                     CheckWindowShadingControlFrameDivider(state, "GetRectSubSurfaces", ErrorsFound, SurfNum, FrameField);
    5657             : 
    5658             :                 } // check on non-opaquedoor subsurfaces
    5659             : 
    5660         130 :                 CheckSubSurfaceMiscellaneous(state,
    5661             :                                              "GetRectSubSurfaces",
    5662             :                                              ErrorsFound,
    5663             :                                              SurfNum,
    5664          65 :                                              state.dataIPShortCut->cAlphaArgs(1),
    5665          65 :                                              state.dataIPShortCut->cAlphaArgs(2),
    5666          65 :                                              AddedSubSurfaces);
    5667             : 
    5668             :             } // Getting Items
    5669             :         }
    5670         771 :     }
    5671             : 
    5672        5964 :     void CheckWindowShadingControlFrameDivider(EnergyPlusData &state,
    5673             :                                                std::string_view const cRoutineName, // routine name calling this one (for error messages)
    5674             :                                                bool &ErrorsFound,                   // true if errors have been found or are found here
    5675             :                                                int const SurfNum,                   // current surface number
    5676             :                                                int const FrameField                 // field number for frame/divider
    5677             :     )
    5678             :     {
    5679             : 
    5680             :         // SUBROUTINE INFORMATION:
    5681             :         //       AUTHOR         Linda Lawrie
    5682             :         //       DATE WRITTEN   December 2008
    5683             :         //       MODIFIED       na
    5684             :         //       RE-ENGINEERED  na
    5685             : 
    5686             :         // PURPOSE OF THIS SUBROUTINE:
    5687             :         // This routine performs checks on WindowShadingControl settings and Frame/Divider Settings.
    5688             : 
    5689             :         // Using/Aliasing
    5690             : 
    5691             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5692             :         int ConstrNumSh;    // Construction number with Shade
    5693             :         int ConstrNum;      // Construction number
    5694             :         int ShDevNum;       // Shading Device number
    5695             :         int Lay;            // Layer number
    5696             :         int TotGlassLayers; // Number of glass layers in window construction
    5697             :         int TotLayers;      // Number of layers in unshaded construction
    5698             :         int TotShLayers;    // Number of layers in shaded construction
    5699             :         int MatGap;         // Gap material number
    5700             :         int MatGap1;        // Material number of gap to left (outer side) of between-glass shade/blind
    5701             :         int MatGap2;        // Material number of gap to right (inner side) of between-glass shade/blind
    5702             :         int MatSh;          // Between-glass shade/blind material number
    5703             :         Real64 MatGapCalc;  // Calculated MatGap diff for shaded vs non-shaded constructions
    5704             : 
    5705             :         // If WindowShadingControl has been specified for this window --
    5706             :         // Set shaded construction number if shaded construction was specified in WindowShadingControl.
    5707             :         // Otherwise, create shaded construction if WindowShadingControl for this window has
    5708             :         // interior or exterior shade/blind (but not between-glass shade/blind) specified.
    5709             : 
    5710        6111 :         for (std::size_t shadeControlIndex = 0; shadeControlIndex < state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.size();
    5711             :              ++shadeControlIndex) {
    5712         147 :             int WSCPtr = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList[shadeControlIndex];
    5713         147 :             ConstrNumSh = 0;
    5714         147 :             if (!ErrorsFound && state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl) {
    5715         147 :                 ConstrNumSh = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex];
    5716         147 :                 if (ConstrNumSh > 0) {
    5717         129 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNumSh;
    5718             :                 } else {
    5719          18 :                     if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType) ||
    5720           0 :                         ANY_EXTERIOR_SHADE_BLIND_SCREEN(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5721          18 :                         ShDevNum = state.dataSurface->WindowShadingControl(WSCPtr).ShadingDevice;
    5722          18 :                         if (ShDevNum > 0) {
    5723          18 :                             CreateShadedWindowConstruction(state, SurfNum, WSCPtr, ShDevNum, shadeControlIndex);
    5724          18 :                             ConstrNumSh = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
    5725             :                         }
    5726             :                     }
    5727             :                 }
    5728             :             }
    5729             : 
    5730             :             // Error checks for shades and blinds
    5731             : 
    5732         147 :             ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    5733         147 :             if (!ErrorsFound && WSCPtr > 0 && ConstrNum > 0 && ConstrNumSh > 0) {
    5734             : 
    5735         147 :                 if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5736          80 :                     TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
    5737          80 :                     TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
    5738          80 :                     if (TotShLayers - 1 != TotLayers) {
    5739           0 :                         ShowWarningError(
    5740             :                             state,
    5741             :                             "WindowShadingControl: Interior shade or blind: Potential problem in match of unshaded/shaded constructions, "
    5742             :                             "shaded should have 1 more layers than unshaded.");
    5743           0 :                         ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
    5744           0 :                         ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
    5745           0 :                         ShowContinueError(state,
    5746             :                                           "If preceding two constructions are same name, you have likely specified a WindowShadingControl (Field #3) "
    5747             :                                           "with the Window Construction rather than a shaded construction.");
    5748             :                     }
    5749         232 :                     for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    5750         304 :                         if (state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay) !=
    5751         152 :                             state.dataConstruction->Construct(ConstrNumSh).LayerPoint(Lay)) {
    5752           0 :                             ErrorsFound = true;
    5753           0 :                             ShowSevereError(state,
    5754           0 :                                             " The glass and gas layers in the shaded and unshaded constructions do not match for window=" +
    5755           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    5756           0 :                             ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
    5757           0 :                             ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
    5758           0 :                             break;
    5759             :                         }
    5760             :                     }
    5761             :                 }
    5762             : 
    5763         147 :                 if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5764          28 :                     TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
    5765          28 :                     TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
    5766          28 :                     if (TotShLayers - 1 != TotLayers) {
    5767           0 :                         ShowWarningError(state,
    5768             :                                          "WindowShadingControl: Exterior shade, screen or blind: Potential problem in match of unshaded/shaded "
    5769             :                                          "constructions, shaded should have 1 more layer than unshaded.");
    5770           0 :                         ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
    5771           0 :                         ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
    5772           0 :                         ShowContinueError(
    5773             :                             state,
    5774             :                             "If preceding two constructions have the same name, you have likely specified a WindowShadingControl (Field "
    5775             :                             "#3) with the Window Construction rather than a shaded construction.");
    5776             :                     }
    5777          76 :                     for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    5778          96 :                         if (state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay) !=
    5779          48 :                             state.dataConstruction->Construct(ConstrNumSh).LayerPoint(Lay + 1)) {
    5780           0 :                             ErrorsFound = true;
    5781           0 :                             ShowSevereError(state,
    5782           0 :                                             " The glass and gas layers in the shaded and unshaded constructions do not match for window=" +
    5783           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    5784           0 :                             ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
    5785           0 :                             ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
    5786           0 :                             break;
    5787             :                         }
    5788             :                     }
    5789             :                 }
    5790             : 
    5791         147 :                 if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5792             :                     // Divider not allowed with between-glass shade or blind
    5793           9 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
    5794           0 :                         if (state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth > 0.0) {
    5795           0 :                             ShowWarningError(state,
    5796           0 :                                              "A divider cannot be specified for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    5797           0 :                             ShowContinueError(state, ", which has a between-glass shade or blind.");
    5798           0 :                             ShowContinueError(state, "Calculation will proceed without the divider for this window.");
    5799           0 :                             state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth = 0.0;
    5800             :                         }
    5801             :                     }
    5802             :                     // Check consistency of gap widths between unshaded and shaded constructions
    5803           9 :                     TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
    5804           9 :                     TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
    5805           9 :                     TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
    5806           9 :                     if (TotShLayers - 2 != TotLayers) {
    5807           0 :                         ShowWarningError(
    5808             :                             state,
    5809             :                             "WindowShadingControl: Between Glass Shade/Blind: Potential problem in match of unshaded/shaded constructions, "
    5810             :                             "shaded should have 2 more layers than unshaded.");
    5811           0 :                         ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
    5812           0 :                         ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
    5813           0 :                         ShowContinueError(state,
    5814             :                                           "If preceding two constructions are same name, you have likely specified a WindowShadingControl (Field #3) "
    5815             :                                           "with the Window Construction rather than a shaded construction.");
    5816             :                     }
    5817          18 :                     if (state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayers) !=
    5818           9 :                         state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotShLayers)) {
    5819           0 :                         ShowSevereError(state,
    5820           0 :                                         std::string{cRoutineName} + ": Mis-match in unshaded/shaded inside layer materials.  These should match.");
    5821           0 :                         ShowContinueError(state,
    5822           0 :                                           "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name + ", Material=" +
    5823           0 :                                               state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayers)).Name);
    5824           0 :                         ShowContinueError(
    5825             :                             state,
    5826           0 :                             "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name + ", Material=" +
    5827           0 :                                 state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotShLayers)).Name);
    5828           0 :                         ErrorsFound = true;
    5829             :                     }
    5830           9 :                     if (state.dataConstruction->Construct(ConstrNum).LayerPoint(1) != state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1)) {
    5831           0 :                         ShowSevereError(state,
    5832           0 :                                         std::string{cRoutineName} + ": Mis-match in unshaded/shaded inside layer materials.  These should match.");
    5833           0 :                         ShowContinueError(state,
    5834           0 :                                           "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name + ", Material=" +
    5835           0 :                                               state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(1)).Name);
    5836           0 :                         ShowContinueError(state,
    5837           0 :                                           "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name + ", Material=" +
    5838           0 :                                               state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1)).Name);
    5839           0 :                         ErrorsFound = true;
    5840             :                     }
    5841           9 :                     if (TotGlassLayers == 2 || TotGlassLayers == 3) {
    5842           9 :                         MatGap = state.dataConstruction->Construct(ConstrNum).LayerPoint(2 * TotGlassLayers - 2);
    5843           9 :                         MatGap1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers - 2);
    5844           9 :                         MatGap2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers);
    5845           9 :                         MatSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers - 1);
    5846           9 :                         if (state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::BGBlind) {
    5847          10 :                             MatGapCalc = std::abs(state.dataMaterial->Material(MatGap).Thickness - (state.dataMaterial->Material(MatGap1).Thickness +
    5848           5 :                                                                                                     state.dataMaterial->Material(MatGap2).Thickness));
    5849           5 :                             if (MatGapCalc > 0.001) {
    5850           0 :                                 ShowSevereError(state,
    5851           0 :                                                 std::string{cRoutineName} + ": The gap width(s) for the unshaded window construction " +
    5852           0 :                                                     state.dataConstruction->Construct(ConstrNum).Name);
    5853           0 :                                 ShowContinueError(state,
    5854           0 :                                                   "are inconsistent with the gap widths for shaded window construction " +
    5855           0 :                                                       state.dataConstruction->Construct(ConstrNumSh).Name);
    5856           0 :                                 ShowContinueError(state,
    5857           0 :                                                   "for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5858             :                                                       ", which has a between-glass blind.");
    5859           0 :                                 ShowContinueError(state,
    5860           0 :                                                   format("..Material={} thickness={:.3R} -",
    5861           0 :                                                          state.dataMaterial->Material(MatGap).Name,
    5862           0 :                                                          state.dataMaterial->Material(MatGap).Thickness));
    5863           0 :                                 ShowContinueError(state,
    5864           0 :                                                   format("..( Material={} thickness={:.3R} +",
    5865           0 :                                                          state.dataMaterial->Material(MatGap1).Name,
    5866           0 :                                                          state.dataMaterial->Material(MatGap1).Thickness));
    5867           0 :                                 ShowContinueError(state,
    5868           0 :                                                   format("..Material={} thickness={:.3R} )=[{:.3R}] >.001",
    5869           0 :                                                          state.dataMaterial->Material(MatGap2).Name,
    5870           0 :                                                          state.dataMaterial->Material(MatGap2).Thickness,
    5871           0 :                                                          MatGapCalc));
    5872           0 :                                 ErrorsFound = true;
    5873             :                             }
    5874             :                         } else { // Between-glass shade
    5875           8 :                             MatGapCalc = std::abs(state.dataMaterial->Material(MatGap).Thickness -
    5876           8 :                                                   (state.dataMaterial->Material(MatGap1).Thickness + state.dataMaterial->Material(MatGap2).Thickness +
    5877           4 :                                                    state.dataMaterial->Material(MatSh).Thickness));
    5878           4 :                             if (MatGapCalc > 0.001) {
    5879           0 :                                 ShowSevereError(state,
    5880           0 :                                                 std::string{cRoutineName} + ": The gap width(s) for the unshaded window construction " +
    5881           0 :                                                     state.dataConstruction->Construct(ConstrNum).Name);
    5882           0 :                                 ShowContinueError(state,
    5883           0 :                                                   "are inconsistent with the gap widths for shaded window construction " +
    5884           0 :                                                       state.dataConstruction->Construct(ConstrNumSh).Name);
    5885           0 :                                 ShowContinueError(state,
    5886           0 :                                                   "for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5887             :                                                       ", which has a between-glass shade.");
    5888           0 :                                 ShowContinueError(state,
    5889           0 :                                                   format("..Material={} thickness={:.3R} -",
    5890           0 :                                                          state.dataMaterial->Material(MatGap).Name,
    5891           0 :                                                          state.dataMaterial->Material(MatGap).Thickness));
    5892           0 :                                 ShowContinueError(state,
    5893           0 :                                                   format("...( Material={} thickness={:.3R} +",
    5894           0 :                                                          state.dataMaterial->Material(MatGap1).Name,
    5895           0 :                                                          state.dataMaterial->Material(MatGap1).Thickness));
    5896           0 :                                 ShowContinueError(state,
    5897           0 :                                                   format("..Material={} thickness={:.3R} +",
    5898           0 :                                                          state.dataMaterial->Material(MatGap2).Name,
    5899           0 :                                                          state.dataMaterial->Material(MatGap2).Thickness));
    5900           0 :                                 ShowContinueError(state,
    5901           0 :                                                   format("..Material={} thickness={:.3R} )=[{:.3R}] >.001",
    5902           0 :                                                          state.dataMaterial->Material(MatSh).Name,
    5903           0 :                                                          state.dataMaterial->Material(MatSh).Thickness,
    5904           0 :                                                          MatGapCalc));
    5905           0 :                                 ErrorsFound = true;
    5906             :                             }
    5907             :                         }
    5908             :                     }
    5909             :                 }
    5910             :             }
    5911             :         }
    5912        5964 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    5913        5964 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides != 3) { // Rectangular Window
    5914             :             // Initialize the FrameDivider number for this window. W5FrameDivider will be positive if
    5915             :             // this window's construction came from the Window5 data file and that construction had an
    5916             :             // associated frame or divider. It will be zero if the window's construction is not from the
    5917             :             // Window5 data file, or the construction is from the data file, but the construction has no
    5918             :             // associated frame or divider. Note that if there is a FrameDivider candidate for this
    5919             :             // window from the Window5 data file it is used instead of the window's input FrameDivider.
    5920             : 
    5921        5962 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5922        5962 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider =
    5923        5962 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).W5FrameDivider;
    5924             : 
    5925             :                 // Warning if FrameAndDivider for this window is over-ridden by one from Window5 Data File
    5926        5962 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0 && !state.dataIPShortCut->lAlphaFieldBlanks(FrameField)) {
    5927           0 :                     ShowSevereError(state,
    5928           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    5929           0 :                                         state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" + state.dataIPShortCut->cAlphaArgs(FrameField) +
    5930             :                                         "\"");
    5931           0 :                     ShowContinueError(state,
    5932           0 :                                       "will be replaced with FrameAndDivider from Window5 Data File entry " +
    5933           0 :                                           state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name);
    5934             :                 }
    5935             : 
    5936        5962 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(FrameField) && state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider == 0) {
    5937         373 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider =
    5938         373 :                         UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(FrameField), state.dataSurface->FrameDivider);
    5939         373 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider == 0) {
    5940           0 :                         if (!state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
    5941           0 :                             ShowSevereError(state,
    5942           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5943           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" +
    5944           0 :                                                 state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
    5945           0 :                             ErrorsFound = true;
    5946             :                         } else {
    5947           0 :                             ShowSevereError(state,
    5948           0 :                                             cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5949           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" +
    5950           0 :                                                 state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
    5951           0 :                             ShowContinueError(state, "...Frame/Divider is not supported in Equivalent Layer Window model.");
    5952             :                         }
    5953             :                     }
    5954             :                     // Divider not allowed with between-glass shade or blind
    5955         414 :                     for (int WSCPtr : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList) {
    5956          41 :                         if (!ErrorsFound && WSCPtr > 0 && ConstrNumSh > 0) {
    5957          41 :                             if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5958           1 :                                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
    5959           1 :                                     if (state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth >
    5960             :                                         0.0) {
    5961           0 :                                         ShowSevereError(state,
    5962           0 :                                                         cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5963           0 :                                                             "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" +
    5964           0 :                                                             state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
    5965           0 :                                         ShowContinueError(state,
    5966             :                                                           "Divider cannot be specified because the construction has a between-glass shade or blind.");
    5967           0 :                                         ShowContinueError(state, "Calculation will proceed without the divider for this window.");
    5968           0 :                                         ShowContinueError(
    5969             :                                             state,
    5970           0 :                                             format("Divider width = [{:.2R}].",
    5971           0 :                                                    state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider)
    5972           0 :                                                        .DividerWidth));
    5973           0 :                                         state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth =
    5974             :                                             0.0;
    5975             :                                     }
    5976             :                                 } // End of check if window has divider
    5977             :                             }     // End of check if window has a between-glass shade or blind
    5978             :                         }         // End of check if window has a shaded construction
    5979             :                     }             // end of looping through window shading controls of window
    5980             :                 }                 // End of check if window has an associated FrameAndDivider
    5981             :             }                     // End of check if window has a construction
    5982             :         }
    5983             : 
    5984        5964 :         if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
    5985           3 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
    5986             :                 // Equivalent Layer window does not have frame/divider model
    5987           0 :                 ShowSevereError(state,
    5988           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    5989           0 :                                     state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" + state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
    5990           0 :                 ShowContinueError(state, "Frame/Divider is not supported in Equivalent Layer Window model.");
    5991           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider = 0;
    5992             :             }
    5993             :         }
    5994        5964 :     }
    5995             : 
    5996        6438 :     void CheckSubSurfaceMiscellaneous(EnergyPlusData &state,
    5997             :                                       std::string_view const cRoutineName,       // routine name calling this one (for error messages)
    5998             :                                       bool &ErrorsFound,                         // true if errors have been found or are found here
    5999             :                                       int const SurfNum,                         // current surface number
    6000             :                                       std::string const &SubSurfaceName,         // name of the surface
    6001             :                                       std::string const &SubSurfaceConstruction, // name of the construction
    6002             :                                       int &AddedSubSurfaces)
    6003             :     {
    6004             : 
    6005             :         // SUBROUTINE INFORMATION:
    6006             :         //       AUTHOR         Linda Lawrie
    6007             :         //       DATE WRITTEN   December 2008
    6008             :         //       MODIFIED       na
    6009             :         //       RE-ENGINEERED  na
    6010             : 
    6011             :         // PURPOSE OF THIS SUBROUTINE:
    6012             :         // This routine performs miscellaneous checks on subsurfaces: Windows, GlassDoors, Doors, Tubular Devices.
    6013             : 
    6014             :         // Using/Aliasing
    6015             : 
    6016             :         using namespace DataErrorTracking;
    6017             : 
    6018             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6019             :         int NumShades; // count on number of shading layers
    6020             :         int Lay;       // Layer number
    6021             :         int LayerPtr;  // Layer pointer
    6022             :         int ConstrNum; // Construction number
    6023             :         int Found;     // when item is found
    6024             : 
    6025             :         // Warning if window has multiplier > 1 and SolarDistribution = FullExterior or FullInteriorExterior
    6026             : 
    6027       13850 :         if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6028        6944 :              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) &&
    6029       17579 :             static_cast<int>(state.dataHeatBal->SolarDistribution) > static_cast<int>(DataHeatBalance::Shadowing::Minimal) &&
    6030        5171 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier > 1.0) {
    6031           6 :             if (state.dataGlobal->DisplayExtraWarnings) {
    6032           0 :                 ShowWarningError(state,
    6033           0 :                                  std::string{cRoutineName} + ": A Multiplier > 1.0 for window/glass door " +
    6034           0 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    6035           0 :                 ShowContinueError(state, "in conjunction with SolarDistribution = FullExterior or FullInteriorExterior");
    6036           0 :                 ShowContinueError(state, "can cause inaccurate shadowing on the window and/or");
    6037           0 :                 ShowContinueError(state, "inaccurate interior solar distribution from the window.");
    6038             :             }
    6039           6 :             ++state.dataErrTracking->TotalMultipliedWindows;
    6040             :         }
    6041             : 
    6042             :         //  Require that a construction referenced by a surface that is a window
    6043             :         //  NOT have a shading device layer; use WindowShadingControl to specify a shading device.
    6044        6438 :         ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    6045        6438 :         if (ConstrNum > 0) {
    6046        6438 :             NumShades = 0;
    6047       16990 :             for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    6048       10552 :                 LayerPtr = state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay);
    6049       10552 :                 if (LayerPtr == 0) continue; // Error is caught already, will terminate later
    6050       31656 :                 if (state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::Shade ||
    6051       21104 :                     state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::WindowBlind ||
    6052       10552 :                     state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::Screen)
    6053           0 :                     ++NumShades;
    6054             :             }
    6055        6438 :             if (NumShades != 0) {
    6056           0 :                 ShowSevereError(state, std::string{cRoutineName} + ": Window \"" + SubSurfaceName + "\" must not directly reference");
    6057           0 :                 ShowContinueError(state, "a Construction (i.e, \"" + SubSurfaceConstruction + "\") with a shading device.");
    6058           0 :                 ShowContinueError(state, "Use WindowShadingControl to specify a shading device for a window.");
    6059           0 :                 ErrorsFound = true;
    6060             :             }
    6061             :         }
    6062             : 
    6063             :         // Disallow glass transmittance dirt factor for interior windows and glass doors
    6064             : 
    6065        6541 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment &&
    6066         171 :             (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6067          80 :              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor)) {
    6068          12 :             ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    6069          12 :             if (ConstrNum > 0) {
    6070          24 :                 for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    6071          12 :                     LayerPtr = state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay);
    6072          24 :                     if (state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::WindowGlass &&
    6073          12 :                         state.dataMaterial->Material(LayerPtr).GlassTransDirtFactor < 1.0) {
    6074           0 :                         ShowSevereError(state,
    6075           0 :                                         std::string{cRoutineName} + ": Interior Window or GlassDoor " + SubSurfaceName + " has a glass layer with");
    6076           0 :                         ShowContinueError(state, "Dirt Correction Factor for Solar and Visible Transmittance < 1.0");
    6077           0 :                         ShowContinueError(state, "A value less than 1.0 for this factor is only allowed for exterior windows and glass doors.");
    6078           0 :                         ErrorsFound = true;
    6079             :                     }
    6080             :                 }
    6081             :             }
    6082             :         }
    6083             : 
    6084             :         // If this is a window with a construction from the Window5DataFile, call routine that will
    6085             :         // (1) if one glazing system on Data File, give warning message if window height or width
    6086             :         //     differ by more than 10% from those of the glazing system on the Data File;
    6087             :         // (2) if two glazing systems (separated by a mullion) on Data File, create a second window
    6088             :         //     and adjust the dimensions of the original and second windows to those on the Data File
    6089             : 
    6090        6438 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    6091             : 
    6092        6438 :             if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).FromWindow5DataFile) {
    6093             : 
    6094           8 :                 ModifyWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
    6095             : 
    6096             :             } else {
    6097             :                 // Calculate net area for base surface (note that ModifyWindow, above, adjusts net area of
    6098             :                 // base surface for case where window construction is from Window5 Data File
    6099             :                 // In case there is in error in this window's base surface (i.e. none)..
    6100        6430 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf > 0) {
    6101        6430 :                     state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -=
    6102        6430 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6103             : 
    6104             :                     // Subtract TDD:DIFFUSER area from other side interzone surface
    6105        6432 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser) &&
    6106           2 :                         not_blank(state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf)
    6107             :                                       .ExtBoundCondName)) { // Base surface is an interzone surface
    6108             :                         // Lookup interzone surface of the base surface
    6109             :                         // (Interzone surfaces have not been assigned yet, but all base surfaces should already be loaded.)
    6110           4 :                         Found = UtilityRoutines::FindItemInList(
    6111           2 :                             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).ExtBoundCondName,
    6112           2 :                             state.dataSurfaceGeometry->SurfaceTmp,
    6113             :                             SurfNum);
    6114           2 :                         if (Found != 0) state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6115             :                     }
    6116        6430 :                     if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
    6117           0 :                         ShowSevereError(state,
    6118           0 :                                         std::string{cRoutineName} + ": Surface Openings have too much area for base surface=" +
    6119           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name);
    6120           0 :                         ShowContinueError(state, "Opening Surface creating error=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    6121           0 :                         ErrorsFound = true;
    6122             :                     }
    6123             :                     // Net area of base surface with unity window multipliers (used in shadowing checks)
    6124             :                     // For Windows, Glass Doors and Doors, just one area is subtracted.  For the rest, should be
    6125             :                     // full area.
    6126        7404 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6127         974 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) {
    6128        5962 :                         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
    6129        5962 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    6130         468 :                     } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door) { // Door, TDD:Diffuser, TDD:DOME
    6131         464 :                         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
    6132         464 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    6133             :                     } else {
    6134           4 :                         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
    6135           4 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6136             :                     }
    6137             :                 }
    6138             :             }
    6139             :         }
    6140        6438 :     }
    6141             : 
    6142         107 :     void MakeRelativeRectangularVertices(EnergyPlusData &state,
    6143             :                                          int const BaseSurfNum, // Base surface
    6144             :                                          int const SurfNum,
    6145             :                                          Real64 const XCoord,
    6146             :                                          Real64 const ZCoord,
    6147             :                                          Real64 const Length,
    6148             :                                          Real64 const Height)
    6149             :     {
    6150             : 
    6151             :         // SUBROUTINE INFORMATION:
    6152             :         //       AUTHOR         Linda Lawrie
    6153             :         //       DATE WRITTEN   December 2008
    6154             :         //       MODIFIED       na
    6155             :         //       RE-ENGINEERED  na
    6156             : 
    6157             :         // PURPOSE OF THIS SUBROUTINE:
    6158             :         // This routine creates world/3d coordinates for rectangular surfaces using relative X and Z, length & height.
    6159             : 
    6160             :         // METHODOLOGY EMPLOYED:
    6161             :         // na
    6162             : 
    6163             :         // REFERENCES:
    6164             :         // na
    6165             : 
    6166             :         // Using/Aliasing
    6167             :         using namespace Vectors;
    6168             : 
    6169             :         // Locals
    6170             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    6171             : 
    6172             :         // SUBROUTINE PARAMETER DEFINITIONS:
    6173             :         // na
    6174             : 
    6175             :         // INTERFACE BLOCK SPECIFICATIONS:
    6176             :         // na
    6177             : 
    6178             :         // DERIVED TYPE DEFINITIONS:
    6179             :         // na
    6180             : 
    6181             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6182             :         Real64 SurfAzimuth; // Surface Azimuth/Facing (same as Base Surface)
    6183             :         Real64 SurfTilt;    // Tilt (same as Base Surface)
    6184             :         Real64 XLLC;
    6185             :         Real64 YLLC;
    6186             :         Real64 ZLLC;
    6187             :         Real64 CosSurfAzimuth;
    6188             :         Real64 SinSurfAzimuth;
    6189             :         Real64 CosSurfTilt;
    6190             :         Real64 SinSurfTilt;
    6191             :         Real64 BaseCosSurfAzimuth;
    6192             :         Real64 BaseSinSurfAzimuth;
    6193             :         Real64 BaseCosSurfTilt;
    6194             :         Real64 BaseSinSurfTilt;
    6195         214 :         Array1D<Real64> XX(4);
    6196         214 :         Array1D<Real64> YY(4);
    6197             :         Real64 Perimeter;
    6198             :         int n;
    6199             :         int Vrt;
    6200             : 
    6201         107 :         if (BaseSurfNum == 0) return; // invalid base surface, don't bother
    6202             : 
    6203             :         // Tilt and Facing (Azimuth) will be same as the Base Surface
    6204             : 
    6205         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = Height;
    6206         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = Length;
    6207             : 
    6208         107 :         SurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
    6209         107 :         SurfTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
    6210         107 :         CosSurfAzimuth = std::cos(SurfAzimuth * DataGlobalConstants::DegToRadians);
    6211         107 :         SinSurfAzimuth = std::sin(SurfAzimuth * DataGlobalConstants::DegToRadians);
    6212         107 :         CosSurfTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
    6213         107 :         SinSurfTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
    6214         107 :         BaseCosSurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim;
    6215         107 :         BaseSinSurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6216         107 :         BaseCosSurfTilt = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt;
    6217         107 :         BaseSinSurfTilt = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6218             : 
    6219         214 :         XLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x - XCoord * BaseCosSurfAzimuth -
    6220         107 :                ZCoord * BaseCosSurfTilt * BaseSinSurfAzimuth;
    6221         214 :         YLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y + XCoord * BaseSinSurfAzimuth -
    6222         107 :                ZCoord * BaseCosSurfTilt * BaseCosSurfAzimuth;
    6223         107 :         ZLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z + ZCoord * BaseSinSurfTilt;
    6224             : 
    6225         107 :         XX(1) = 0.0;
    6226         107 :         XX(2) = 0.0;
    6227         107 :         XX(3) = Length;
    6228         107 :         XX(4) = Length;
    6229         107 :         YY(1) = Height;
    6230         107 :         YY(4) = Height;
    6231         107 :         YY(3) = 0.0;
    6232         107 :         YY(2) = 0.0;
    6233             : 
    6234         535 :         for (n = 1; n <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++n) {
    6235         428 :             Vrt = n;
    6236         428 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).x = XLLC - XX(n) * CosSurfAzimuth - YY(n) * CosSurfTilt * SinSurfAzimuth;
    6237         428 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).y = YLLC + XX(n) * SinSurfAzimuth - YY(n) * CosSurfTilt * CosSurfAzimuth;
    6238         428 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).z = ZLLC + YY(n) * SinSurfTilt;
    6239             :         }
    6240             : 
    6241         214 :         CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    6242         107 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    6243         107 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    6244         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    6245         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    6246         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6247         214 :         CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    6248         107 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    6249         107 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    6250         642 :         DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    6251         107 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    6252             :                                 SurfAzimuth,
    6253             :                                 SurfTilt,
    6254         107 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    6255         107 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    6256         107 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    6257         107 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
    6258         107 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    6259         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfAzimuth;
    6260         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    6261         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    6262         107 :             ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6263             :         // Sine and cosine of azimuth and tilt
    6264         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = SinSurfAzimuth;
    6265         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = CosSurfAzimuth;
    6266         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = SinSurfTilt;
    6267         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = CosSurfTilt;
    6268         266 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
    6269         157 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
    6270          50 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door)
    6271          42 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    6272             :         // Outward normal unit vector (pointing away from room)
    6273         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    6274         428 :         for (n = 1; n <= 3; ++n) {
    6275         321 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    6276          22 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    6277         321 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    6278          85 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    6279         321 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    6280         214 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    6281             :         }
    6282             : 
    6283             :         //  IF (SurfaceTmp(SurfNum)%Class == SurfaceClass::Roof .and. SurfTilt > 80.) THEN
    6284             :         //    WRITE(TiltString,'(F5.1)') SurfTilt
    6285             :         //    TiltString=ADJUSTL(TiltString)
    6286             :         //    CALL ShowWarningError(state, 'Roof/Ceiling Tilt='//TRIM(TiltString)//', much greater than expected tilt of 0,'// &
    6287             :         //                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
    6288             :         //                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
    6289             :         //  ENDIF
    6290             :         //  IF (SurfaceTmp(SurfNum)%Class == SurfaceClass::Floor .and. SurfTilt < 170.) THEN
    6291             :         //    WRITE(TiltString,'(F5.1)') SurfTilt
    6292             :         //    TiltString=ADJUSTL(TiltString)
    6293             :         //    CALL ShowWarningError(state, 'Floor Tilt='//TRIM(TiltString)//', much less than expected tilt of 180,'//   &
    6294             :         //                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
    6295             :         //                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
    6296             :         //  ENDIF
    6297         266 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6298         157 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    6299          50 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    6300          65 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area *= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    6301             :         // Can perform tests on this surface here
    6302         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    6303             :         // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    6304             :         // surfaces
    6305         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    6306         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    6307             : 
    6308         107 :         Perimeter = distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides),
    6309         107 :                              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1));
    6310         428 :         for (Vrt = 2; Vrt <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vrt) {
    6311         321 :             Perimeter +=
    6312         642 :                 distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt), state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt - 1));
    6313             :         }
    6314         107 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
    6315             : 
    6316             :         // Call to transform vertices
    6317             : 
    6318         107 :         TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6319             :     }
    6320             : 
    6321         771 :     void GetAttShdSurfaceData(EnergyPlusData &state,
    6322             :                               bool &ErrorsFound,   // Error flag indicator (true if errors found)
    6323             :                               int &SurfNum,        // Count of Current SurfaceNumber
    6324             :                               int const TotShdSubs // Number of Attached Shading SubSurfaces to obtain
    6325             :     )
    6326             :     {
    6327             :         // SUBROUTINE INFORMATION:
    6328             :         //       AUTHOR         Linda Lawrie
    6329             :         //       DATE WRITTEN   May 2000
    6330             : 
    6331             :         // PURPOSE OF THIS SUBROUTINE:
    6332             :         // This subroutine gets the HeatTransfer Surface Data,
    6333             :         // checks it for errors, etc.
    6334             : 
    6335             :         // Using/Aliasing
    6336             :         using ScheduleManager::CheckScheduleValueMinMax;
    6337             :         using ScheduleManager::GetScheduleIndex;
    6338             :         using ScheduleManager::GetScheduleMaxValue;
    6339             :         using ScheduleManager::GetScheduleMinValue;
    6340             : 
    6341             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6342             :         int IOStat;     // IO Status when calling get input subroutine
    6343             :         int NumAlphas;  // Number of alpha names being passed
    6344             :         int NumNumbers; // Number of properties being passed
    6345             :         int Found;      // For matching interzone surfaces
    6346             :         int Loop;
    6347             :         Real64 SchedMinValue;
    6348             :         Real64 SchedMaxValue;
    6349             : 
    6350         771 :         if (TotShdSubs > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    6351           1 :             ShowWarningError(state, "Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing");
    6352             :         }
    6353         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    6354         771 :         cCurrentModuleObject = "Shading:Zone:Detailed";
    6355         771 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
    6356         771 :         if (NumAlphas != 3) {
    6357           0 :             ShowSevereError(state,
    6358           0 :                             format("{}: Object Definition indicates not = 3 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
    6359           0 :             ErrorsFound = true;
    6360             :         }
    6361             : 
    6362        1430 :         for (Loop = 1; Loop <= TotShdSubs; ++Loop) {
    6363        4613 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    6364             :                                                                      cCurrentModuleObject,
    6365             :                                                                      Loop,
    6366         659 :                                                                      state.dataIPShortCut->cAlphaArgs,
    6367             :                                                                      NumAlphas,
    6368         659 :                                                                      state.dataIPShortCut->rNumericArgs,
    6369             :                                                                      NumNumbers,
    6370             :                                                                      IOStat,
    6371         659 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    6372         659 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    6373         659 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    6374         659 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    6375             : 
    6376        1318 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    6377         659 :                                                          state.dataSurfaceGeometry->UniqueSurfaceNames,
    6378         659 :                                                          state.dataIPShortCut->cAlphaArgs(1),
    6379             :                                                          cCurrentModuleObject,
    6380         659 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    6381             :                                                          ErrorsFound)) {
    6382           0 :                 continue;
    6383             :             }
    6384             : 
    6385         659 :             ++SurfNum;
    6386         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    6387         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
    6388         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    6389         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(2);
    6390             :             //  The subsurface inherits properties from the base surface
    6391             :             //  Exterior conditions, Zone, etc.
    6392             :             //  We can figure out the base surface though, because they've all been entered
    6393        1977 :             Found = UtilityRoutines::FindItemInList(
    6394        1977 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
    6395         659 :             if (Found > 0) {
    6396             :                 // SurfaceTmp(SurfNum)%BaseSurf=Found
    6397         659 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    6398         659 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    6399         659 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    6400         659 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
    6401         659 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
    6402        1318 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
    6403        1318 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
    6404             :             } else {
    6405           0 :                 ShowSevereError(state,
    6406           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    6407           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    6408           0 :                 ErrorsFound = true;
    6409             :             }
    6410         659 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) {
    6411           0 :                 ShowSevereError(state,
    6412           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    6413           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    6414           0 :                 ShowContinueError(state, "...trying to attach a shading device to an interzone surface.");
    6415           0 :                 ErrorsFound = true;
    6416           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6417             :                     ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6418             :             }
    6419         659 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    6420           0 :                 ShowSevereError(state,
    6421           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    6422           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    6423           0 :                 ShowContinueError(state, "...trying to attach a shading device to an interior surface.");
    6424           0 :                 ErrorsFound = true;
    6425           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6426             :                     ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6427             :             }
    6428             : 
    6429         659 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    6430         596 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    6431         596 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex == 0) {
    6432           0 :                     ShowSevereError(state,
    6433           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    6434           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + " not found=\"" + state.dataIPShortCut->cAlphaArgs(3));
    6435           0 :                     ErrorsFound = true;
    6436             :                 }
    6437             :             } else {
    6438          63 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    6439             :             }
    6440         659 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex != 0) {
    6441         596 :                 if (!CheckScheduleValueMinMax(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex, ">=", 0.0, "<=", 1.0)) {
    6442           0 :                     ShowSevereError(state,
    6443           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    6444           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    6445             :                                         "\", values not in range [0,1].");
    6446           0 :                     ErrorsFound = true;
    6447             :                 }
    6448         596 :                 SchedMinValue = GetScheduleMinValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    6449         596 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue = SchedMinValue;
    6450         596 :                 SchedMaxValue = GetScheduleMaxValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    6451         596 :                 if (SchedMinValue == 1.0) {
    6452           0 :                     ShowWarningError(state,
    6453           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    6454           0 :                                          state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    6455             :                                          "\", is always transparent.");
    6456           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent = true;
    6457             :                 }
    6458         596 :                 if (SchedMinValue < 0.0) {
    6459           0 :                     ShowSevereError(state,
    6460           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    6461           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    6462             :                                         "\", has schedule values < 0.");
    6463           0 :                     ShowContinueError(state, "...Schedule values < 0 have no meaning for shading elements.");
    6464             :                 }
    6465         596 :                 if (SchedMaxValue > 0.0) {
    6466           8 :                     state.dataSolarShading->anyScheduledShadingSurface = true;
    6467             :                 }
    6468         596 :                 if (SchedMaxValue > 1.0) {
    6469           0 :                     ShowSevereError(state,
    6470           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    6471           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    6472             :                                         "\", has schedule values > 1.");
    6473           0 :                     ShowContinueError(state, "...Schedule values > 1 have no meaning for shading elements.");
    6474             :                 }
    6475         596 :                 if (std::abs(SchedMinValue - SchedMaxValue) > 1.0e-6) {
    6476           0 :                     state.dataSurface->ShadingTransmittanceVaries = true;
    6477             :                 }
    6478             :             }
    6479         659 :             if (state.dataIPShortCut->lNumericFieldBlanks(1) || state.dataIPShortCut->rNumericArgs(1) == DataGlobalConstants::AutoCalculate) {
    6480           2 :                 state.dataIPShortCut->rNumericArgs(1) = (NumNumbers - 1) / 3;
    6481           2 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
    6482           2 :                 if (mod(NumNumbers - 1, 3) != 0) {
    6483           0 :                     ShowWarningError(state,
    6484           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
    6485           0 :                                          format("{} not even multiple of 3. Will read in {}",
    6486           0 :                                                 state.dataIPShortCut->cNumericFieldNames(1),
    6487           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    6488             :                 }
    6489           2 :                 if (state.dataIPShortCut->rNumericArgs(1) < 3) {
    6490           0 :                     ShowSevereError(state,
    6491           0 :                                     format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    6492             :                                            cCurrentModuleObject,
    6493           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6494           0 :                                            state.dataIPShortCut->cNumericFieldNames(1),
    6495           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    6496           0 :                     ErrorsFound = true;
    6497           0 :                     continue;
    6498             :                 }
    6499             :             } else {
    6500         657 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
    6501             :             }
    6502         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6503         659 :             GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({2, _}));
    6504         659 :             CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6505             :             //    IF (SurfaceTmp(SurfNum)%Sides == 3) THEN
    6506             :             //      CALL ShowWarningError(state, TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
    6507             :             //                        ' should not be triangular.')
    6508             :             //      CALL ShowContinueError(state, '...Check results carefully.')
    6509             :             //      ErrorsFound=.TRUE.
    6510             :             //    ENDIF
    6511             :             // Reset surface to be "detached"
    6512         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6513             :             //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6514         659 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6515             :             // SurfaceTmp(SurfNum)%ZoneName='  '
    6516         659 :             if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6517         659 :                 MakeMirrorSurface(state, SurfNum);
    6518             :             }
    6519             :         }
    6520         771 :     }
    6521             : 
    6522         771 :     void GetSimpleShdSurfaceData(EnergyPlusData &state,
    6523             :                                  bool &ErrorsFound,                // Error flag indicator (true if errors found)
    6524             :                                  int &SurfNum,                     // Count of Current SurfaceNumber
    6525             :                                  int const TotOverhangs,           // Number of Overhangs to obtain
    6526             :                                  int const TotOverhangsProjection, // Number of Overhangs (projection) to obtain
    6527             :                                  int const TotFins,                // Number of Fins to obtain
    6528             :                                  int const TotFinsProjection       // Number of Fins (projection) to obtain
    6529             :     )
    6530             :     {
    6531             : 
    6532             :         // SUBROUTINE INFORMATION:
    6533             :         //       AUTHOR         Linda Lawrie
    6534             :         //       DATE WRITTEN   January 2009
    6535             :         //       MODIFIED       na
    6536             :         //       RE-ENGINEERED  na
    6537             : 
    6538             :         // PURPOSE OF THIS SUBROUTINE:
    6539             :         // Get simple overhang and fin descriptions.
    6540             : 
    6541             :         // Using/Aliasing
    6542             :         using namespace Vectors;
    6543             : 
    6544             :         // SUBROUTINE PARAMETER DEFINITIONS:
    6545         771 :         static Array1D_string const cModuleObjects(4, {"Shading:Overhang", "Shading:Overhang:Projection", "Shading:Fin", "Shading:Fin:Projection"});
    6546             : 
    6547             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6548             :         int Item;
    6549             :         int ItemsToGet;
    6550             :         int Loop;
    6551             :         int NumAlphas;
    6552             :         int NumNumbers;
    6553             :         int IOStat; // IO Status when calling get input subroutine
    6554             :         int Found;  // For matching base surfaces
    6555             :         Real64 Depth;
    6556             :         Real64 Length;
    6557             :         Real64 Xp;
    6558             :         Real64 Yp;
    6559             :         Real64 Zp;
    6560             :         Real64 XLLC;
    6561             :         Real64 YLLC;
    6562             :         int BaseSurfNum;
    6563             :         Real64 TiltAngle;
    6564             :         bool MakeFin;
    6565             : 
    6566         779 :         if ((TotOverhangs + TotOverhangsProjection + TotFins + TotFinsProjection) > 0 &&
    6567           8 :             state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    6568           0 :             ShowWarningError(state, "Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing");
    6569             :         }
    6570         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    6571        3855 :         for (Item = 1; Item <= 4; ++Item) {
    6572             : 
    6573        3084 :             cCurrentModuleObject = cModuleObjects(Item);
    6574        3084 :             if (Item == 1) {
    6575         771 :                 ItemsToGet = TotOverhangs;
    6576        2313 :             } else if (Item == 2) {
    6577         771 :                 ItemsToGet = TotOverhangsProjection;
    6578        1542 :             } else if (Item == 3) {
    6579         771 :                 ItemsToGet = TotFins;
    6580             :             } else { // ! (Item == 4) THEN
    6581         771 :                 ItemsToGet = TotFinsProjection;
    6582             :             }
    6583             : 
    6584        3117 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    6585         231 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    6586             :                                                                          cCurrentModuleObject,
    6587             :                                                                          Loop,
    6588          33 :                                                                          state.dataIPShortCut->cAlphaArgs,
    6589             :                                                                          NumAlphas,
    6590          33 :                                                                          state.dataIPShortCut->rNumericArgs,
    6591             :                                                                          NumNumbers,
    6592             :                                                                          IOStat,
    6593          33 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    6594          33 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    6595          33 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    6596          33 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    6597             : 
    6598          66 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    6599          33 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    6600          33 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    6601             :                                                              cCurrentModuleObject,
    6602          33 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    6603             :                                                              ErrorsFound)) {
    6604           0 :                     continue;
    6605             :                 }
    6606             : 
    6607          33 :                 ++SurfNum;
    6608          33 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    6609          33 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
    6610          33 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    6611             :                 // this object references a window or door....
    6612          99 :                 Found = UtilityRoutines::FindItemInList(
    6613          99 :                     state.dataIPShortCut->cAlphaArgs(2), state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
    6614          33 :                 if (Found > 0) {
    6615          33 :                     BaseSurfNum = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurf;
    6616          33 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurfName;
    6617          33 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    6618          33 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    6619          33 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    6620          33 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
    6621          33 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
    6622          66 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
    6623          66 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
    6624             :                 } else {
    6625           0 :                     ShowSevereError(state,
    6626           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    6627           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    6628           0 :                     ErrorsFound = true;
    6629           0 :                     continue;
    6630             :                 }
    6631          33 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) {
    6632           0 :                     ShowSevereError(state,
    6633           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    6634           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    6635           0 :                     ShowContinueError(state, "...trying to attach a shading device to an interzone surface.");
    6636           0 :                     ErrorsFound = true;
    6637           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6638             :                         ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6639             :                 }
    6640          33 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    6641           0 :                     ShowSevereError(state,
    6642           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
    6643           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    6644           0 :                     ShowContinueError(state, "...trying to attach a shading device to an interior surface.");
    6645           0 :                     ErrorsFound = true;
    6646           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6647             :                         ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6648             :                 }
    6649             : 
    6650          33 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    6651             : 
    6652             :                 //===== Overhang =====
    6653             : 
    6654          33 :                 if (Item < 3) {
    6655             :                     //  Found is the surface window or door.
    6656             :                     //   N1,  \field Height above Window or Door
    6657             :                     //        \units m
    6658             :                     //   N2,  \field Tilt Angle from Window/Door
    6659             :                     //        \units deg
    6660             :                     //        \default 90
    6661             :                     //        \minimum 0
    6662             :                     //        \maximum 180
    6663             :                     //   N3,  \field Left extension from Window/Door Width
    6664             :                     //        \units m
    6665             :                     //   N4,  \field Right extension from Window/Door Width
    6666             :                     //        \note N3 + N4 + Window/Door Width is Overhang Length
    6667             :                     //        \units m
    6668             :                     //   N5;  \field Depth
    6669             :                     //        \units m
    6670             :                     // for projection option:
    6671             :                     //   N5;  \field Depth as Fraction of Window/Door Height
    6672             :                     //        \units m
    6673          48 :                     Length = state.dataIPShortCut->rNumericArgs(3) + state.dataIPShortCut->rNumericArgs(4) +
    6674          24 :                              state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
    6675          24 :                     if (Item == 1) {
    6676          23 :                         Depth = state.dataIPShortCut->rNumericArgs(5);
    6677           1 :                     } else if (Item == 2) {
    6678           1 :                         Depth = state.dataIPShortCut->rNumericArgs(5) * state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
    6679             :                     }
    6680             : 
    6681          24 :                     if (Length * Depth <= 0.0) {
    6682           0 :                         ShowSevereError(state,
    6683           0 :                                         format("{}=\"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
    6684             :                                                cCurrentModuleObject,
    6685           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
    6686           0 :                                                Length * Depth));
    6687           0 :                         continue;
    6688             :                     }
    6689             : 
    6690          24 :                     TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt + state.dataIPShortCut->rNumericArgs(2);
    6691          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
    6692          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    6693          24 :                         ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6694          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth;
    6695             : 
    6696             :                     // Make it relative to surface origin.....
    6697          24 :                     Xp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
    6698          24 :                     Yp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
    6699          24 :                     Zp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
    6700             : 
    6701          48 :                     XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
    6702          24 :                            Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6703             : 
    6704          24 :                     YLLC =
    6705          48 :                         -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
    6706          48 :                             state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
    6707          24 :                         Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
    6708          24 :                         Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6709             : 
    6710          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    6711          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6712             : 
    6713          48 :                     MakeRelativeRectangularVertices(state,
    6714             :                                                     BaseSurfNum,
    6715             :                                                     SurfNum,
    6716          24 :                                                     XLLC - state.dataIPShortCut->rNumericArgs(3),
    6717          24 :                                                     YLLC + state.dataSurfaceGeometry->SurfaceTmp(Found).Height +
    6718          24 :                                                         state.dataIPShortCut->rNumericArgs(1),
    6719             :                                                     Length,
    6720             :                                                     Depth);
    6721             : 
    6722             :                     // Reset surface to be "detached"
    6723             :                     //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6724             :                     //    SurfaceTmp(SurfNum)%ZoneName='  '
    6725             : 
    6726          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6727          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6728             : 
    6729             :                     // and mirror
    6730          24 :                     if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6731          24 :                         MakeMirrorSurface(state, SurfNum);
    6732             :                     }
    6733             : 
    6734             :                 } else { // Fins
    6735             : 
    6736             :                     //===== Fins =====
    6737             : 
    6738             :                     //===== Left Fin =====
    6739             : 
    6740             :                     //   N1,  \field Left Extension from Window/Door
    6741             :                     //        \units m
    6742             :                     //   N2,  \field Left Distance Above Top of Window
    6743             :                     //        \units m
    6744             :                     //   N3,  \field Left Distance Below Bottom of Window
    6745             :                     //        \units m
    6746             :                     //        \note N2 + N3 + height of Window/Door is height of Fin
    6747             :                     //   N4,  \field Left Tilt Angle from Window/Door
    6748             :                     //        \units deg
    6749             :                     //        \default 90
    6750             :                     //        \minimum 0
    6751             :                     //        \maximum 180
    6752             :                     //   N5,  \field Left Depth
    6753             :                     //        \units m
    6754             :                     // for projection option:
    6755             :                     //   N5,  \field Left Depth as Fraction of Window/Door Width
    6756             :                     //        \units m
    6757           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + " Left";
    6758          18 :                     Length = state.dataIPShortCut->rNumericArgs(2) + state.dataIPShortCut->rNumericArgs(3) +
    6759           9 :                              state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
    6760           9 :                     if (Item == 3) {
    6761           8 :                         Depth = state.dataIPShortCut->rNumericArgs(5);
    6762           1 :                     } else if (Item == 4) {
    6763           1 :                         Depth = state.dataIPShortCut->rNumericArgs(5) * state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
    6764             :                     }
    6765             : 
    6766           9 :                     MakeFin = true;
    6767           9 :                     if (Length * Depth <= 0.0) {
    6768           0 :                         ShowWarningError(state,
    6769           0 :                                          format("{}=Left Fin of \"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
    6770             :                                                 cCurrentModuleObject,
    6771           0 :                                                 state.dataIPShortCut->cAlphaArgs(1),
    6772           0 :                                                 Length * Depth));
    6773           0 :                         MakeFin = false;
    6774             :                     }
    6775             : 
    6776           9 :                     if (MakeFin) {
    6777           9 :                         TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
    6778           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
    6779           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    6780           9 :                             ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6781           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth =
    6782           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth - (180.0 - state.dataIPShortCut->rNumericArgs(4));
    6783             : 
    6784             :                         // Make it relative to surface origin.....
    6785             : 
    6786           9 :                         Xp =
    6787           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
    6788           9 :                         Yp =
    6789           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
    6790           9 :                         Zp =
    6791           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
    6792             : 
    6793          18 :                         XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
    6794           9 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6795             : 
    6796          27 :                         YLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
    6797          18 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
    6798          18 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim *
    6799           9 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
    6800           9 :                                Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6801             : 
    6802           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim =
    6803           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
    6804           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim =
    6805           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
    6806           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt =
    6807           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
    6808           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt =
    6809           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
    6810             : 
    6811           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    6812           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6813             : 
    6814          27 :                         MakeRelativeRectangularVertices(state,
    6815             :                                                         BaseSurfNum,
    6816             :                                                         SurfNum,
    6817           9 :                                                         XLLC - state.dataIPShortCut->rNumericArgs(1),
    6818           9 :                                                         YLLC - state.dataIPShortCut->rNumericArgs(3),
    6819             :                                                         -Depth,
    6820             :                                                         Length);
    6821             : 
    6822             :                         // Reset surface to be "detached"
    6823             :                         //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6824             :                         //    SurfaceTmp(SurfNum)%ZoneName='  '
    6825             : 
    6826           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6827           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6828             : 
    6829             :                         // and mirror
    6830           9 :                         if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6831           9 :                             MakeMirrorSurface(state, SurfNum);
    6832             :                         }
    6833             :                     } else {
    6834           0 :                         --SurfNum;
    6835             :                     }
    6836             : 
    6837             :                     //===== Right Fin =====
    6838             : 
    6839             :                     //   N6,  \field Right Extension from Window/Door
    6840             :                     //        \units m
    6841             :                     //   N7,  \field Right Distance Above Top of Window
    6842             :                     //        \units m
    6843             :                     //   N8,  \field Right Distance Below Bottom of Window
    6844             :                     //        \note N7 + N8 + height of Window/Door is height of Fin
    6845             :                     //        \units m
    6846             :                     //   N9,  \field Right Tilt Angle from Window/Door
    6847             :                     //        \units deg
    6848             :                     //        \default 90
    6849             :                     //        \minimum 0
    6850             :                     //        \maximum 180
    6851             :                     //   N10; \field Right Depth
    6852             :                     //        \units m
    6853             :                     // for projection option:
    6854             :                     //   N10; \field Right Depth as Fraction of Window/Door Width
    6855             :                     //        \units m
    6856             : 
    6857           9 :                     ++SurfNum;
    6858          18 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name =
    6859          27 :                         state.dataIPShortCut->cAlphaArgs(1) + " Right"; // Set the Surface Name in the Derived Type
    6860           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
    6861           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    6862           9 :                     BaseSurfNum = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurf;
    6863           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurfName;
    6864           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    6865           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    6866           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    6867           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
    6868           9 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
    6869          18 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
    6870          18 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
    6871             : 
    6872           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    6873          18 :                     Length = state.dataIPShortCut->rNumericArgs(7) + state.dataIPShortCut->rNumericArgs(8) +
    6874           9 :                              state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
    6875           9 :                     if (Item == 3) {
    6876           8 :                         Depth = state.dataIPShortCut->rNumericArgs(10);
    6877           1 :                     } else if (Item == 4) {
    6878           1 :                         Depth = state.dataIPShortCut->rNumericArgs(10) * state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
    6879             :                     }
    6880             : 
    6881           9 :                     MakeFin = true;
    6882           9 :                     if (Length * Depth <= 0.0) {
    6883           0 :                         ShowWarningError(state,
    6884           0 :                                          format("{}=Right Fin of \"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
    6885             :                                                 cCurrentModuleObject,
    6886           0 :                                                 state.dataIPShortCut->cAlphaArgs(1),
    6887           0 :                                                 Length * Depth));
    6888           0 :                         MakeFin = false;
    6889             :                     }
    6890             : 
    6891           9 :                     if (MakeFin) {
    6892             :                         // Make it relative to surface origin.....
    6893             : 
    6894           9 :                         Xp =
    6895           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
    6896           9 :                         Yp =
    6897           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
    6898           9 :                         Zp =
    6899           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
    6900             : 
    6901          18 :                         XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
    6902           9 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6903             : 
    6904          27 :                         YLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
    6905          18 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
    6906          18 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim *
    6907           9 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
    6908           9 :                                Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6909             : 
    6910           9 :                         TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
    6911           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
    6912           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    6913           9 :                             ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6914           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth =
    6915           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth - (180.0 - state.dataIPShortCut->rNumericArgs(9));
    6916           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim =
    6917           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
    6918           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim =
    6919           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
    6920           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt =
    6921           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
    6922           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt =
    6923           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
    6924             : 
    6925           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    6926           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6927             : 
    6928          27 :                         MakeRelativeRectangularVertices(state,
    6929             :                                                         BaseSurfNum,
    6930             :                                                         SurfNum,
    6931           9 :                                                         XLLC + state.dataSurfaceGeometry->SurfaceTmp(Found).Width +
    6932           9 :                                                             state.dataIPShortCut->rNumericArgs(6),
    6933           9 :                                                         YLLC - state.dataIPShortCut->rNumericArgs(8),
    6934             :                                                         -Depth,
    6935             :                                                         Length);
    6936             : 
    6937             :                         // Reset surface to be "detached"
    6938             :                         //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6939             :                         //    SurfaceTmp(SurfNum)%ZoneName='  '
    6940             : 
    6941           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6942           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6943             : 
    6944             :                         // and mirror
    6945           9 :                         if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6946           9 :                             MakeMirrorSurface(state, SurfNum);
    6947             :                         }
    6948             :                     } else {
    6949           0 :                         --SurfNum;
    6950             :                     }
    6951             :                 }
    6952             :             }
    6953             :         }
    6954         771 :     }
    6955             : 
    6956         771 :     void GetIntMassSurfaceData(EnergyPlusData &state,
    6957             :                                bool &ErrorsFound, // Error flag indicator (true if errors found)
    6958             :                                int &SurfNum       // Count of Current SurfaceNumber
    6959             :     )
    6960             :     {
    6961             : 
    6962             :         // SUBROUTINE INFORMATION:
    6963             :         //       AUTHOR         Linda Lawrie
    6964             :         //       DATE WRITTEN   May 2000
    6965             :         //       MODIFIED       na
    6966             :         //       RE-ENGINEERED  na
    6967             : 
    6968             :         // PURPOSE OF THIS SUBROUTINE:
    6969             :         // This subroutine gets the Internal Surface Data,
    6970             :         // checks it for errors, etc.
    6971             : 
    6972             :         // METHODOLOGY EMPLOYED:
    6973             :         // na
    6974             : 
    6975             :         // REFERENCES:
    6976             :         // Internal Mass Surface Definition
    6977             :         // Surface:HeatTransfer:InternalMass,
    6978             :         //       \note used to describe internal zone surface area that does not need to be part of geometric representation
    6979             :         //  A1 , \field User Supplied Surface Name
    6980             :         //       \type alpha
    6981             :         //       \reference SurfaceNames
    6982             :         //  A2 , \field Construction Name of the Surface
    6983             :         //       \note To be matched with a construction in this input file
    6984             :         //       \type object-list
    6985             :         //       \object-list ConstructionNames
    6986             :         //  A3 , \field Interior Environment
    6987             :         //       \note Zone the surface is a part of
    6988             :         //       \type object-list
    6989             :         //       \object-list ZoneNames
    6990             :         //  N1,  \field View factor to Person (to people?)
    6991             :         //       \type real
    6992             :         //       \note from the interior of the surface
    6993             :         //  N2 ; \field Surface area
    6994             :         //       \units m2
    6995             : 
    6996             :         // Using/Aliasing
    6997             :         using namespace Vectors;
    6998             :         using General::CheckCreatedZoneItemName;
    6999             : 
    7000             :         // SUBROUTINE PARAMETER DEFINITIONS:
    7001             :         static constexpr std::string_view RoutineName("GetIntMassSurfaceData: ");
    7002             : 
    7003             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7004             :         int IOStat;                // IO Status when calling get input subroutine
    7005             :         int SurfaceNumAlpha;       // Number of material alpha names being passed
    7006             :         int SurfaceNumArg;         // Number of material properties being passed
    7007             :         int ZoneNum;               // index to a zone
    7008         771 :         int NumIntMassSurfaces(0); // total count of internal mass surfaces
    7009             :         bool errFlag;              //  local error flag
    7010         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7011         771 :         cCurrentModuleObject = "InternalMass";
    7012         771 :         int TotIntMass = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7013         771 :         if (TotIntMass == 0) return;
    7014             : 
    7015         164 :         state.dataSurface->IntMassObjects.allocate(TotIntMass);
    7016             : 
    7017             :         // scan for use of Zone lists in InternalMass objects
    7018         164 :         errFlag = false;
    7019         164 :         NumIntMassSurfaces = 0;
    7020        2446 :         for (int Item = 1; Item <= TotIntMass; ++Item) {
    7021       15974 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7022             :                                                                      cCurrentModuleObject,
    7023             :                                                                      Item,
    7024        2282 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7025             :                                                                      SurfaceNumAlpha,
    7026        2282 :                                                                      state.dataIPShortCut->rNumericArgs,
    7027             :                                                                      SurfaceNumArg,
    7028             :                                                                      IOStat,
    7029        2282 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7030        2282 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7031        2282 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7032        2282 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7033             : 
    7034        4564 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    7035        2282 :                                                          state.dataSurfaceGeometry->UniqueSurfaceNames,
    7036        2282 :                                                          state.dataIPShortCut->cAlphaArgs(1),
    7037             :                                                          cCurrentModuleObject,
    7038        2282 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    7039             :                                                          ErrorsFound)) {
    7040           0 :                 continue;
    7041             :             }
    7042             : 
    7043        2282 :             state.dataSurface->IntMassObjects(Item).Name = state.dataIPShortCut->cAlphaArgs(1);
    7044        2282 :             state.dataSurface->IntMassObjects(Item).GrossArea = state.dataIPShortCut->rNumericArgs(1);
    7045        6846 :             state.dataSurface->IntMassObjects(Item).Construction = UtilityRoutines::FindItemInList(
    7046        6846 :                 state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    7047        2282 :             state.dataSurface->IntMassObjects(Item).ZoneOrZoneListName = state.dataIPShortCut->cAlphaArgs(3);
    7048        2282 :             int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    7049        2282 :             int ZLItem = 0;
    7050        2282 :             if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0)
    7051           1 :                 ZLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->ZoneList);
    7052        2282 :             if (Item1 > 0) {
    7053        2281 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7054        2281 :                     ++NumIntMassSurfaces;
    7055             :                 }
    7056        2281 :                 state.dataSurface->IntMassObjects(Item).NumOfZones = 1;
    7057        2281 :                 state.dataSurface->IntMassObjects(Item).ZoneListActive = false;
    7058        2281 :                 state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = Item1;
    7059           1 :             } else if (ZLItem > 0) {
    7060           1 :                 NumIntMassSurfaces += state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
    7061           1 :                 state.dataSurface->IntMassObjects(Item).NumOfZones = state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
    7062           1 :                 state.dataSurface->IntMassObjects(Item).ZoneListActive = true;
    7063           1 :                 state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = ZLItem;
    7064             :             } else {
    7065           0 :                 ShowSevereError(state,
    7066           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
    7067           0 :                                     state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\" not found.");
    7068           0 :                 ++SurfNum;
    7069           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    7070           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    7071           0 :                 ErrorsFound = true;
    7072           0 :                 errFlag = true;
    7073             :             }
    7074             : 
    7075        2282 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7076           0 :                 state.dataSurface->IntMassObjects(Item).spaceOrSpaceListName = state.dataIPShortCut->cAlphaArgs(4);
    7077           0 :                 int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
    7078           0 :                 int SLItem = 0;
    7079           0 :                 if (Item1 == 0 && int(state.dataHeatBal->spaceList.size()) > 0)
    7080           0 :                     SLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->spaceList);
    7081           0 :                 if (Item1 > 0) {
    7082           0 :                     ++NumIntMassSurfaces;
    7083           0 :                     state.dataSurface->IntMassObjects(Item).numOfSpaces = 1;
    7084           0 :                     state.dataSurface->IntMassObjects(Item).spaceListActive = false;
    7085           0 :                     state.dataSurface->IntMassObjects(Item).spaceOrSpaceListPtr = Item1;
    7086           0 :                     if (!state.dataSurface->IntMassObjects(Item).ZoneListActive) {
    7087           0 :                         if (state.dataHeatBal->space(Item1).zoneNum != state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr) {
    7088           0 :                             ShowSevereError(state,
    7089           0 :                                             cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
    7090           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) +
    7091           0 :                                                 "\" is not part of Zone =\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
    7092           0 :                             ErrorsFound = true;
    7093           0 :                             errFlag = true;
    7094             :                         }
    7095             :                     }
    7096           0 :                 } else if (SLItem > 0) {
    7097           0 :                     int numOfSpaces = int(state.dataHeatBal->spaceList(SLItem).numListSpaces);
    7098           0 :                     NumIntMassSurfaces += numOfSpaces;
    7099           0 :                     state.dataSurface->IntMassObjects(Item).numOfSpaces = numOfSpaces;
    7100           0 :                     state.dataSurface->IntMassObjects(Item).spaceListActive = true;
    7101           0 :                     state.dataSurface->IntMassObjects(Item).spaceOrSpaceListPtr = SLItem;
    7102             :                 } else {
    7103           0 :                     ShowSevereError(state,
    7104           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
    7105           0 :                                         state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\" not found.");
    7106           0 :                     ++SurfNum;
    7107           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    7108           0 :                     ErrorsFound = true;
    7109           0 :                     errFlag = true;
    7110             :                 }
    7111             :             }
    7112             : 
    7113        2282 :             if (errFlag) {
    7114           0 :                 ShowSevereError(state, std::string{RoutineName} + "Errors with invalid names in " + cCurrentModuleObject + " objects.");
    7115           0 :                 ShowContinueError(state, "...These will not be read in.  Other errors may occur.");
    7116           0 :                 NumIntMassSurfaces = 0;
    7117             :             }
    7118             : 
    7119        2282 :             if (state.dataSurface->IntMassObjects(Item).Construction == 0) {
    7120           0 :                 ErrorsFound = true;
    7121           0 :                 ShowSevereError(state,
    7122           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
    7123           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + " not found=" + state.dataIPShortCut->cAlphaArgs(2));
    7124        2282 :             } else if (state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Item).Construction).TypeIsWindow) {
    7125           0 :                 ErrorsFound = true;
    7126           0 :                 ShowSevereError(state,
    7127           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    7128           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    7129             :                                     "\" - has Window materials.");
    7130             :             } else {
    7131        2282 :                 state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Item).Construction).IsUsed = true;
    7132             :             }
    7133             :         }
    7134             : 
    7135         164 :         if (NumIntMassSurfaces > 0) {
    7136         164 :             int spaceNum = 0;
    7137        2446 :             for (int Loop = 1; Loop <= TotIntMass; ++Loop) {
    7138        2282 :                 int numberOfZonesOrSpaces = 1;
    7139        2282 :                 if (state.dataSurface->IntMassObjects(Loop).ZoneListActive) {
    7140           1 :                     numberOfZonesOrSpaces = state.dataSurface->IntMassObjects(Loop).NumOfZones;
    7141        2281 :                 } else if (state.dataSurface->IntMassObjects(Loop).spaceListActive) {
    7142           0 :                     numberOfZonesOrSpaces = state.dataSurface->IntMassObjects(Loop).numOfSpaces;
    7143             :                 }
    7144             : 
    7145        4566 :                 for (int Item1 = 1; Item1 <= numberOfZonesOrSpaces; ++Item1) {
    7146             : 
    7147        2284 :                     ++SurfNum;
    7148             : 
    7149        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = state.dataSurface->IntMassObjects(Loop).Construction;
    7150        2284 :                     if (!state.dataSurface->IntMassObjects(Loop).ZoneListActive && !state.dataSurface->IntMassObjects(Loop).spaceListActive) {
    7151        2281 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr;
    7152        2281 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = state.dataSurface->IntMassObjects(Loop).spaceOrSpaceListPtr;
    7153        2281 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataSurface->IntMassObjects(Loop).Name;
    7154        2281 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::IntMass;
    7155        2281 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListName;
    7156        2281 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    7157             :                     } else {
    7158           3 :                         if (state.dataSurface->IntMassObjects(Loop).ZoneListActive) {
    7159          18 :                             CheckCreatedZoneItemName(
    7160             :                                 state,
    7161             :                                 RoutineName,
    7162             :                                 cCurrentModuleObject,
    7163             :                                 state.dataHeatBal
    7164           3 :                                     ->Zone(state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).Zone(Item1))
    7165             :                                     .Name,
    7166           3 :                                 state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).MaxZoneNameLength,
    7167           3 :                                 state.dataSurface->IntMassObjects(Loop).Name,
    7168           3 :                                 state.dataSurfaceGeometry->SurfaceTmp,
    7169           3 :                                 SurfNum - 1,
    7170           3 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    7171             :                                 errFlag);
    7172             : 
    7173           3 :                             ZoneNum = state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).Zone(Item1);
    7174           0 :                         } else if (state.dataSurface->IntMassObjects(Loop).spaceListActive) {
    7175           0 :                             spaceNum = state.dataHeatBal->spaceList(state.dataSurface->IntMassObjects(Loop).spaceOrSpaceListPtr).spaces(Item1);
    7176           0 :                             ZoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
    7177           0 :                             const std::string spaceName = state.dataHeatBal->space(spaceNum).Name;
    7178           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = spaceName + ' ' + state.dataSurface->IntMassObjects(Loop).Name;
    7179           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
    7180             :                         }
    7181           3 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
    7182           3 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::IntMass;
    7183           3 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataHeatBal->Zone(ZoneNum).Name;
    7184           3 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    7185           3 :                         if (errFlag) ErrorsFound = true;
    7186             :                     }
    7187             : 
    7188        2284 :                     if (state.dataSurface->IntMassObjects(Loop).Construction > 0) {
    7189        2284 :                         if (state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Loop).Construction).IsUsed) {
    7190        2284 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    7191        2284 :                                 state.dataSurface->IntMassObjects(Loop).Construction;
    7192             :                         }
    7193             :                     }
    7194        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = state.dataSurface->IntMassObjects(Loop).GrossArea;
    7195        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    7196        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    7197        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    7198        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = 1.0;
    7199        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = 90.0;
    7200        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    7201        2284 :                         ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    7202        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = 0.0; // Tuned Was std::cos( 90.0 * DegToRadians )
    7203        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = 1.0; // Tuned Was std::sin( 90.0 * DegToRadians )
    7204        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = 0.0;
    7205        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = 1.0; // Tuned Was std::cos( 0.0 )
    7206        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = 0.0; // Tuned Was std::sin( 0.0 )
    7207             :                     // Outward normal unit vector (pointing away from room)
    7208        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz;
    7209        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5;
    7210        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
    7211        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
    7212        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
    7213        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    7214        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    7215        2284 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    7216             :                 }
    7217             :             }
    7218             :         }
    7219             :     }
    7220             : 
    7221         771 :     int GetNumIntMassSurfaces(EnergyPlusData &state) // Number of Internal Mass Surfaces to obtain
    7222             : 
    7223             :     {
    7224             :         // Counts internal mass surfaces applied to zones and zone lists
    7225             : 
    7226             :         // Using/Aliasing
    7227             : 
    7228             :         int IOStat;          // IO Status when calling get input subroutine
    7229             :         int SurfaceNumAlpha; // Number of material alpha names being passed
    7230             :         int SurfaceNumArg;   // Number of material properties being passed
    7231             :         int NumIntMassSurf;  // total count of internal mass surfaces
    7232             : 
    7233         771 :         NumIntMassSurf = 0;
    7234         771 :         int TotIntMass = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "InternalMass");
    7235             : 
    7236         771 :         if (TotIntMass == 0) return NumIntMassSurf;
    7237         164 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7238         164 :         cCurrentModuleObject = "InternalMass";
    7239             :         // scan for zones and zone lists in InternalMass objects
    7240        2446 :         for (int Item = 1; Item <= TotIntMass; ++Item) {
    7241       15974 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7242             :                                                                      cCurrentModuleObject,
    7243             :                                                                      Item,
    7244        2282 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7245             :                                                                      SurfaceNumAlpha,
    7246        2282 :                                                                      state.dataIPShortCut->rNumericArgs,
    7247             :                                                                      SurfaceNumArg,
    7248             :                                                                      IOStat,
    7249        2282 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7250        2282 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7251        2282 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7252        2282 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7253             : 
    7254        2282 :             int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    7255        2282 :             int ZLItem = 0;
    7256        2282 :             if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0)
    7257           1 :                 ZLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->ZoneList);
    7258        2282 :             if (Item1 > 0) {
    7259        2281 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7260        2281 :                     ++NumIntMassSurf;
    7261             :                 }
    7262           1 :             } else if (ZLItem > 0) {
    7263           1 :                 NumIntMassSurf += state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
    7264             :             }
    7265             : 
    7266        2282 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7267           0 :                 int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
    7268           0 :                 int SLItem = 0;
    7269           0 :                 if (Item1 == 0 && int(state.dataHeatBal->spaceList.size()) > 0)
    7270           0 :                     SLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->spaceList);
    7271           0 :                 if (Item1 > 0) {
    7272           0 :                     ++NumIntMassSurf;
    7273           0 :                 } else if (SLItem > 0) {
    7274           0 :                     int numOfSpaces = int(state.dataHeatBal->spaceList(SLItem).numListSpaces);
    7275           0 :                     NumIntMassSurf += numOfSpaces;
    7276             :                 }
    7277             :             }
    7278             :         }
    7279         164 :         NumIntMassSurf = max(NumIntMassSurf, TotIntMass);
    7280         164 :         return NumIntMassSurf;
    7281             :     }
    7282             : 
    7283           9 :     void GetShadingSurfReflectanceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    7284             :     {
    7285             : 
    7286             :         // SUBROUTINE INFORMATION:
    7287             :         //       AUTHOR         Fred Winkelmann
    7288             :         //       DATE WRITTEN   Sept 2003
    7289             :         //       MODIFIED       na
    7290             :         //       RE-ENGINEERED  na
    7291             : 
    7292             :         // PURPOSE OF THIS SUBROUTINE:
    7293             :         // Gets data for a Shading Surface Reflectance object.  This is only called when the
    7294             :         // Solar Distribution is to be calculated for reflectances.
    7295             : 
    7296             :         // Using/Aliasing
    7297             : 
    7298             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7299             : 
    7300             :         int IOStat;                       // IO Status when calling get input subroutine
    7301             :         int NumAlpha;                     // Number of alpha names being passed
    7302             :         int NumProp;                      // Number of properties being passed
    7303             :         int TotShadingSurfaceReflectance; // Total Shading Surface Refleftance statements
    7304             :         int Loop;                         // DO loop index
    7305             :         int SurfNum;                      // Surface number
    7306             :         int GlConstrNum;                  // Glazing construction number
    7307             :         bool WrongSurfaceType;
    7308             : 
    7309             :         // For shading surfaces, initialize value of reflectance values to default values. These values
    7310             :         // may be overridden below for shading surfaces with an associated Shading Surface Reflectance object.
    7311         101 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    7312         266 :             if (!(state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Shading ||
    7313         174 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_F ||
    7314         172 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_B ||
    7315          86 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Overhang ||
    7316          86 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Fin))
    7317          86 :                 continue;
    7318           6 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) = 0.2;
    7319           6 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) = 0.2;
    7320           6 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = 0.0;
    7321           6 :             state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = 0;
    7322             :         }
    7323             : 
    7324             :         // Get the total number of Shading Surface Reflectance objects
    7325           9 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7326           9 :         cCurrentModuleObject = "ShadingProperty:Reflectance";
    7327           9 :         TotShadingSurfaceReflectance = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7328             :         //  IF(TotShadingSurfaceReflectance.EQ.0) RETURN
    7329             : 
    7330          10 :         for (Loop = 1; Loop <= TotShadingSurfaceReflectance; ++Loop) {
    7331             : 
    7332           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7333             :                                                                      cCurrentModuleObject,
    7334             :                                                                      Loop,
    7335           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7336             :                                                                      NumAlpha,
    7337           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    7338             :                                                                      NumProp,
    7339             :                                                                      IOStat,
    7340           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7341           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7342           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7343           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7344           1 :             SurfNum =
    7345           1 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7346           1 :             if (SurfNum == 0) {
    7347           0 :                 ShowWarningError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid specification");
    7348           0 :                 ShowContinueError(state,
    7349           0 :                                   ".. not found " + state.dataIPShortCut->cAlphaFieldNames(1) + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
    7350             :                 //      ErrorsFound =.TRUE.
    7351           0 :                 continue;
    7352             :             }
    7353             : 
    7354             :             // Check that associated surface is a shading surface
    7355           1 :             WrongSurfaceType = false;
    7356           1 :             if (SurfNum != 0) {
    7357           2 :                 if (!(state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Shading ||
    7358           1 :                       state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_F ||
    7359           0 :                       state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_B ||
    7360           0 :                       state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Overhang ||
    7361           0 :                       state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Fin))
    7362           0 :                     WrongSurfaceType = true;
    7363           1 :                 if (WrongSurfaceType) {
    7364           0 :                     ShowSevereError(state,
    7365           0 :                                     "GetShadingSurfReflectanceData: " + cCurrentModuleObject + "=\"" + state.dataSurface->Surface(SurfNum).Name +
    7366             :                                         "\", surface is not a shading surface.");
    7367           0 :                     ErrorsFound = true;
    7368           0 :                     continue;
    7369             :                 }
    7370             :             }
    7371             : 
    7372             :             // If associated surface is a shading surface, set reflectance values
    7373           1 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = state.dataIPShortCut->rNumericArgs(3);
    7374           1 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) =
    7375           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(1);
    7376           1 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) =
    7377           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(2);
    7378           1 :             if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    7379           3 :                 GlConstrNum = UtilityRoutines::FindItemInList(
    7380           3 :                     state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    7381           1 :                 if (GlConstrNum == 0) {
    7382           0 :                     ShowSevereError(state,
    7383           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurface->Surface(SurfNum).Name + "\", " +
    7384           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + " not found=" + state.dataIPShortCut->cAlphaArgs(2));
    7385           0 :                     ErrorsFound = true;
    7386             :                 } else {
    7387           1 :                     state.dataConstruction->Construct(GlConstrNum).IsUsed = true;
    7388             :                 }
    7389           1 :                 state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = GlConstrNum;
    7390             :             }
    7391           3 :             SurfNum = UtilityRoutines::FindItemInList(
    7392           4 :                 "Mir-" + state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7393           1 :             if (SurfNum == 0) continue;
    7394           1 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = state.dataIPShortCut->rNumericArgs(3);
    7395           1 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) =
    7396           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(1);
    7397           1 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) =
    7398           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(2);
    7399           1 :             if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    7400           3 :                 GlConstrNum = UtilityRoutines::FindItemInList(
    7401           3 :                     state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    7402           1 :                 if (GlConstrNum != 0) {
    7403           1 :                     state.dataConstruction->Construct(GlConstrNum).IsUsed = true;
    7404             :                 }
    7405           1 :                 state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = GlConstrNum;
    7406             :             }
    7407             : 
    7408             :         } // End of loop over Shading Surface Reflectance objects
    7409             : 
    7410             :         // Write reflectance values to .eio file.
    7411           9 :         print(state.files.eio,
    7412             :               "! <ShadingProperty Reflectance>,Shading Surface Name,Shading Type,Diffuse Solar Reflectance, Diffuse "
    7413           9 :               "Visible Reflectance,Surface Glazing Fraction,Surface Glazing Contruction\n");
    7414             : 
    7415         101 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    7416         266 :             if (!(state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Shading ||
    7417         174 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_F ||
    7418         172 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_B ||
    7419          86 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Overhang ||
    7420          86 :                   state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Fin))
    7421          86 :                 continue;
    7422             : 
    7423           6 :             constexpr auto fmt{"ShadingProperty Reflectance,{},{},{:.2R},{:.2R},{:.2R}, {}\n"};
    7424           6 :             if (state.dataSurface->SurfShadowGlazingConstruct(SurfNum) != 0) {
    7425          12 :                 print(state.files.eio,
    7426             :                       fmt,
    7427           2 :                       state.dataSurface->Surface(SurfNum).Name,
    7428           4 :                       cSurfaceClass(state.dataSurface->Surface(SurfNum).Class),
    7429           2 :                       state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum),
    7430           2 :                       state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum),
    7431           2 :                       state.dataSurface->SurfShadowGlazingFrac(SurfNum),
    7432           4 :                       state.dataConstruction->Construct(state.dataSurface->SurfShadowGlazingConstruct(SurfNum)).Name);
    7433             :             } else {
    7434          20 :                 print(state.files.eio,
    7435             :                       fmt,
    7436           4 :                       state.dataSurface->Surface(SurfNum).Name,
    7437           8 :                       cSurfaceClass(state.dataSurface->Surface(SurfNum).Class),
    7438           4 :                       state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum),
    7439           4 :                       state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum),
    7440           4 :                       state.dataSurface->SurfShadowGlazingFrac(SurfNum),
    7441           4 :                       "N/A");
    7442             :             }
    7443             :         }
    7444           9 :     }
    7445             : 
    7446         771 :     void GetHTSurfExtVentedCavityData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    7447             :     {
    7448             : 
    7449             :         // SUBROUTINE INFORMATION:
    7450             :         //       AUTHOR         BGriffith
    7451             :         //       DATE WRITTEN   January 2005
    7452             :         //       MODIFIED       na
    7453             :         //       RE-ENGINEERED  na
    7454             : 
    7455             :         // PURPOSE OF THIS SUBROUTINE:
    7456             :         // load input data for Exterior Vented Cavity Special case for heat transfer surfaces
    7457             : 
    7458             :         // METHODOLOGY EMPLOYED:
    7459             :         // usual E+ input processes
    7460             : 
    7461             :         // REFERENCES:
    7462             :         // derived from SUBROUTINE GetTranspiredCollectorInput
    7463             : 
    7464             :         // Using/Aliasing
    7465             : 
    7466             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7467             : 
    7468             :         int Item;          // Item to be "gotten"
    7469             :         int NumAlphas;     // Number of Alphas for each GetObjectItem call
    7470             :         int NumNumbers;    // Number of Numbers for each GetObjectItem call
    7471             :         int MaxNumAlphas;  // argument for call to GetObjectDefMaxArgs
    7472             :         int MaxNumNumbers; // argument for call to GetObjectDefMaxArgs
    7473             :         int Dummy;         // argument for call to GetObjectDefMaxArgs
    7474             :         int IOStatus;      // Used in GetObjectItem
    7475             :         int Found;
    7476             :         int AlphaOffset; // local temp var
    7477        1542 :         std::string Roughness;
    7478             :         int ThisSurf;      // do loop counter
    7479             :         Real64 AvgAzimuth; // temp for error checking
    7480             :         Real64 AvgTilt;    // temp for error checking
    7481             :         int SurfID;        // local surface "pointer"
    7482             :         bool IsBlank;
    7483             :         bool ErrorInName;
    7484         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7485         771 :         cCurrentModuleObject = "SurfaceProperty:ExteriorNaturalVentedCavity";
    7486         771 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Dummy, MaxNumAlphas, MaxNumNumbers);
    7487             : 
    7488         771 :         if (MaxNumNumbers != 8) {
    7489           0 :             ShowSevereError(
    7490           0 :                 state, format("{}: Object Definition indicates not = 8 Number Objects, Number Indicated={}", cCurrentModuleObject, MaxNumNumbers));
    7491           0 :             ErrorsFound = true;
    7492             :         }
    7493             : 
    7494         771 :         state.dataSurface->TotExtVentCav = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7495             : 
    7496         771 :         state.dataSurface->ExtVentedCavity.allocate(state.dataSurface->TotExtVentCav);
    7497             : 
    7498         776 :         for (Item = 1; Item <= state.dataSurface->TotExtVentCav; ++Item) {
    7499          35 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7500             :                                                                      cCurrentModuleObject,
    7501             :                                                                      Item,
    7502           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7503             :                                                                      NumAlphas,
    7504           5 :                                                                      state.dataIPShortCut->rNumericArgs,
    7505             :                                                                      NumNumbers,
    7506             :                                                                      IOStatus,
    7507           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7508           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7509           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7510           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7511             :             // first handle cAlphaArgs
    7512           5 :             ErrorInName = false;
    7513           5 :             IsBlank = false;
    7514             : 
    7515          15 :             UtilityRoutines::VerifyName(state,
    7516           5 :                                         state.dataIPShortCut->cAlphaArgs(1),
    7517           5 :                                         state.dataSurface->ExtVentedCavity,
    7518             :                                         Item - 1,
    7519             :                                         ErrorInName,
    7520             :                                         IsBlank,
    7521          10 :                                         cCurrentModuleObject + " Name");
    7522           5 :             if (ErrorInName) {
    7523           0 :                 ShowContinueError(state, "...cannot not duplicate other names");
    7524           0 :                 ErrorsFound = true;
    7525           0 :                 continue;
    7526             :             }
    7527           5 :             state.dataSurface->ExtVentedCavity(Item).Name = state.dataIPShortCut->cAlphaArgs(1);
    7528             : 
    7529           5 :             state.dataSurface->ExtVentedCavity(Item).OSCMName = state.dataIPShortCut->cAlphaArgs(2);
    7530           5 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    7531          15 :                 Found = UtilityRoutines::FindItemInList(
    7532          15 :                     state.dataSurface->ExtVentedCavity(Item).OSCMName, state.dataSurface->OSCM, state.dataSurface->TotOSCM);
    7533           5 :                 if (Found == 0) {
    7534           0 :                     ShowSevereError(state,
    7535           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7536           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
    7537           0 :                     ErrorsFound = true;
    7538             :                 }
    7539             :             } else {
    7540           0 :                 Found = 0;
    7541           0 :                 ShowSevereError(state,
    7542           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7543           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + " cannot be blank.");
    7544           0 :                 ErrorsFound = true;
    7545             :             }
    7546           5 :             state.dataSurface->ExtVentedCavity(Item).OSCMPtr = Found;
    7547             : 
    7548           5 :             Roughness = state.dataIPShortCut->cAlphaArgs(3);
    7549             :             // Select the correct Number for the associated ascii name for the roughness type
    7550           5 :             if (UtilityRoutines::SameString(Roughness, "VerySmooth")) {
    7551           0 :                 state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::VerySmooth;
    7552           5 :             } else if (UtilityRoutines::SameString(Roughness, "Smooth")) {
    7553           5 :                 state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::Smooth;
    7554           0 :             } else if (UtilityRoutines::SameString(Roughness, "MediumSmooth")) {
    7555           0 :                 state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::MediumSmooth;
    7556           0 :             } else if (UtilityRoutines::SameString(Roughness, "MediumRough")) {
    7557           0 :                 state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::MediumRough;
    7558           0 :             } else if (UtilityRoutines::SameString(Roughness, "Rough")) {
    7559           0 :                 state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::Rough;
    7560           0 :             } else if (UtilityRoutines::SameString(Roughness, "VeryRough")) {
    7561           0 :                 state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::VeryRough;
    7562             :             } // TODO: fix this after creating FindEnumeratedValueIndex()
    7563             : 
    7564             :             // Was it set?
    7565           5 :             if (state.dataSurface->ExtVentedCavity(Item).BaffleRoughness == DataSurfaces::SurfaceRoughness::Invalid) {
    7566           0 :                 ShowSevereError(state,
    7567           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7568           0 :                                     state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
    7569           0 :                 ErrorsFound = true;
    7570             :             }
    7571             : 
    7572           5 :             AlphaOffset = 3;
    7573           5 :             state.dataSurface->ExtVentedCavity(Item).NumSurfs = NumAlphas - AlphaOffset;
    7574           5 :             if (state.dataSurface->ExtVentedCavity(Item).NumSurfs == 0) {
    7575           0 :                 ShowSevereError(state,
    7576           0 :                                 cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name +
    7577             :                                     "\", no underlying surfaces specified. Must have at least one.");
    7578           0 :                 ErrorsFound = true;
    7579           0 :                 continue;
    7580             :             }
    7581           5 :             state.dataSurface->ExtVentedCavity(Item).SurfPtrs.allocate(state.dataSurface->ExtVentedCavity(Item).NumSurfs);
    7582           5 :             state.dataSurface->ExtVentedCavity(Item).SurfPtrs = 0;
    7583          10 :             for (ThisSurf = 1; ThisSurf <= state.dataSurface->ExtVentedCavity(Item).NumSurfs; ++ThisSurf) {
    7584          15 :                 Found = UtilityRoutines::FindItemInList(
    7585          15 :                     state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7586           5 :                 if (Found == 0) {
    7587           0 :                     ShowSevereError(state,
    7588           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7589           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
    7590           0 :                                         state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
    7591           0 :                     ErrorsFound = true;
    7592           0 :                     continue;
    7593             :                 }
    7594             :                 // check that surface is appropriate, Heat transfer, Sun, Wind,
    7595           5 :                 if (!state.dataSurface->Surface(Found).HeatTransSurf) {
    7596           0 :                     ShowSevereError(state,
    7597           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7598           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
    7599           0 :                                         state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
    7600           0 :                     ShowContinueError(state, "...because it is not a Heat Transfer Surface.");
    7601           0 :                     ErrorsFound = true;
    7602           0 :                     continue;
    7603             :                 }
    7604           5 :                 if (!state.dataSurface->Surface(Found).ExtSolar) {
    7605           0 :                     ShowSevereError(state,
    7606           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7607           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
    7608           0 :                                         state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
    7609           0 :                     ShowContinueError(state, "...because it is not exposed to Sun.");
    7610           0 :                     ErrorsFound = true;
    7611           0 :                     continue;
    7612             :                 }
    7613           5 :                 if (!state.dataSurface->Surface(Found).ExtWind) {
    7614           0 :                     ShowSevereError(state,
    7615           0 :                                     cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
    7616           0 :                                         state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
    7617           0 :                                         state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
    7618           0 :                     ShowContinueError(state, "...because it is not exposed to Wind.");
    7619           0 :                     ErrorsFound = true;
    7620           0 :                     continue;
    7621             :                 }
    7622           5 :                 if (state.dataSurface->Surface(Found).ExtBoundCond != OtherSideCondModeledExt) {
    7623           0 :                     ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", is invalid");
    7624           0 :                     ShowContinueError(state,
    7625           0 :                                       "...because " + state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
    7626           0 :                                           state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset) + "\".");
    7627           0 :                     ShowContinueError(state, "...is not an OtherSideConditionedModel surface.");
    7628           0 :                     ErrorsFound = true;
    7629           0 :                     continue;
    7630             :                 }
    7631           5 :                 state.dataSurface->ExtVentedCavity(Item).SurfPtrs(ThisSurf) = Found;
    7632             : 
    7633             :                 // now set info in Surface structure
    7634           5 :                 state.dataSurface->SurfExtCavNum(Found) = Item;
    7635           5 :                 state.dataSurface->SurfExtCavityPresent(Found) = true;
    7636             :             }
    7637             : 
    7638           5 :             if (ErrorsFound) continue; // previous inner do loop may have detected problems that need to be cycle'd again to avoid crash
    7639             : 
    7640             :             // now that we should have all the surfaces, do some preperations and checks.
    7641             : 
    7642             :             // are they all similar tilt and azimuth? Issue warnings so people can do it if they really want
    7643           5 :             Real64 const surfaceArea(sum_sub(state.dataSurface->Surface, &SurfaceData::Area, state.dataSurface->ExtVentedCavity(Item).SurfPtrs));
    7644             :             //            AvgAzimuth = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Azimuth * Surface( ExtVentedCavity( Item ).SurfPtrs
    7645             :             //).Area
    7646             :             //)
    7647             :             ///  sum(  Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
    7648           5 :             AvgAzimuth = sum_product_sub(state.dataSurface->Surface,
    7649             :                                          &SurfaceData::Azimuth,
    7650             :                                          &SurfaceData::Area,
    7651           5 :                                          state.dataSurface->ExtVentedCavity(Item).SurfPtrs) /
    7652             :                          surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
    7653             :             //            AvgTilt = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Tilt * Surface( ExtVentedCavity( Item ).SurfPtrs ).Area )
    7654             :             //            /
    7655             :             // sum(  Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
    7656          10 :             AvgTilt = sum_product_sub(
    7657          10 :                           state.dataSurface->Surface, &SurfaceData::Tilt, &SurfaceData::Area, state.dataSurface->ExtVentedCavity(Item).SurfPtrs) /
    7658             :                       surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
    7659          10 :             for (ThisSurf = 1; ThisSurf <= state.dataSurface->ExtVentedCavity(Item).NumSurfs; ++ThisSurf) {
    7660           5 :                 SurfID = state.dataSurface->ExtVentedCavity(Item).SurfPtrs(ThisSurf);
    7661           5 :                 if (std::abs(state.dataSurface->Surface(SurfID).Azimuth - AvgAzimuth) > 15.0) {
    7662           0 :                     ShowWarningError(state,
    7663           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + ", Surface " +
    7664           0 :                                          state.dataSurface->Surface(SurfID).Name + " has Azimuth different from others in the associated group.");
    7665             :                 }
    7666           5 :                 if (std::abs(state.dataSurface->Surface(SurfID).Tilt - AvgTilt) > 10.0) {
    7667           0 :                     ShowWarningError(state,
    7668           0 :                                      cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + ", Surface " +
    7669           0 :                                          state.dataSurface->Surface(SurfID).Name + " has Tilt different from others in the associated group.");
    7670             :                 }
    7671             : 
    7672             :                 // test that there are no windows.  Now allow windows
    7673             :                 // If (Surface(SurfID)%GrossArea >  Surface(SurfID)%Area) Then
    7674             :                 //      Call ShowWarningError(state, 'Surface '//TRIM(Surface(SurfID)%name)//' has a subsurface whose area is not being ' &
    7675             :                 //         //'subtracted in the group of surfaces associated with '//TRIM(ExtVentedCavity(Item)%Name))
    7676             :                 // endif
    7677             :             }
    7678           5 :             state.dataSurface->ExtVentedCavity(Item).Tilt = AvgTilt;
    7679           5 :             state.dataSurface->ExtVentedCavity(Item).Azimuth = AvgAzimuth;
    7680             : 
    7681             :             // find area weighted centroid.
    7682             :             //            ExtVentedCavity( Item ).Centroid.z = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Centroid.z * Surface(
    7683             :             // ExtVentedCavity(  Item
    7684             :             //).SurfPtrs ).Area ) / sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced
    7685             :             // by below
    7686          15 :             state.dataSurface->ExtVentedCavity(Item).Centroid.z = sum_product_sub(state.dataSurface->Surface,
    7687             :                                                                                   &SurfaceData::Centroid,
    7688             :                                                                                   &Vector::z,
    7689           5 :                                                                                   state.dataSurface->Surface,
    7690             :                                                                                   &SurfaceData::Area,
    7691          10 :                                                                                   state.dataSurface->ExtVentedCavity(Item).SurfPtrs) /
    7692             :                                                                   surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
    7693             : 
    7694             :             // now handle rNumericArgs from input object
    7695           5 :             state.dataSurface->ExtVentedCavity(Item).Porosity = state.dataIPShortCut->rNumericArgs(1);
    7696           5 :             state.dataSurface->ExtVentedCavity(Item).LWEmitt = state.dataIPShortCut->rNumericArgs(2);
    7697           5 :             state.dataSurface->ExtVentedCavity(Item).SolAbsorp = state.dataIPShortCut->rNumericArgs(3);
    7698           5 :             state.dataSurface->ExtVentedCavity(Item).HdeltaNPL = state.dataIPShortCut->rNumericArgs(4);
    7699           5 :             state.dataSurface->ExtVentedCavity(Item).PlenGapThick = state.dataIPShortCut->rNumericArgs(5);
    7700           5 :             if (state.dataSurface->ExtVentedCavity(Item).PlenGapThick <= 0.0) {
    7701           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid .");
    7702           0 :                 ErrorsFound = true;
    7703           0 :                 ShowContinueError(state,
    7704           0 :                                   format("...because field \"{}\" must be greater than Zero=[{:.2T}].",
    7705           0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    7706           0 :                                          state.dataIPShortCut->rNumericArgs(5)));
    7707           0 :                 continue;
    7708             :             }
    7709           5 :             state.dataSurface->ExtVentedCavity(Item).AreaRatio = state.dataIPShortCut->rNumericArgs(6);
    7710           5 :             state.dataSurface->ExtVentedCavity(Item).Cv = state.dataIPShortCut->rNumericArgs(7);
    7711           5 :             state.dataSurface->ExtVentedCavity(Item).Cd = state.dataIPShortCut->rNumericArgs(8);
    7712             : 
    7713             :             // Fill out data we now know
    7714             :             // sum areas of HT surface areas
    7715             :             //            ExtVentedCavity( Item ).ProjArea = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array
    7716             :             // subscript  usage: Replaced by below
    7717           5 :             state.dataSurface->ExtVentedCavity(Item).ProjArea = surfaceArea;
    7718           5 :             if (state.dataSurface->ExtVentedCavity(Item).ProjArea <= 0.0) {
    7719           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid .");
    7720           0 :                 ErrorsFound = true;
    7721           0 :                 ShowContinueError(state,
    7722           0 :                                   format("...because gross area of underlying surfaces must be greater than Zero=[{:.2T}].",
    7723           0 :                                          state.dataSurface->ExtVentedCavity(Item).ProjArea));
    7724           0 :                 continue;
    7725             :             }
    7726           5 :             state.dataSurface->ExtVentedCavity(Item).ActualArea =
    7727           5 :                 state.dataSurface->ExtVentedCavity(Item).ProjArea * state.dataSurface->ExtVentedCavity(Item).AreaRatio;
    7728             : 
    7729          20 :             SetupOutputVariable(state,
    7730             :                                 "Surface Exterior Cavity Baffle Surface Temperature",
    7731             :                                 OutputProcessor::Unit::C,
    7732           5 :                                 state.dataSurface->ExtVentedCavity(Item).Tbaffle,
    7733             :                                 OutputProcessor::SOVTimeStepType::System,
    7734             :                                 OutputProcessor::SOVStoreType::Average,
    7735          10 :                                 state.dataSurface->ExtVentedCavity(Item).Name);
    7736          20 :             SetupOutputVariable(state,
    7737             :                                 "Surface Exterior Cavity Air Drybulb Temperature",
    7738             :                                 OutputProcessor::Unit::C,
    7739           5 :                                 state.dataSurface->ExtVentedCavity(Item).TAirCav,
    7740             :                                 OutputProcessor::SOVTimeStepType::System,
    7741             :                                 OutputProcessor::SOVStoreType::Average,
    7742          10 :                                 state.dataSurface->ExtVentedCavity(Item).Name);
    7743          20 :             SetupOutputVariable(state,
    7744             :                                 "Surface Exterior Cavity Total Natural Ventilation Air Change Rate",
    7745             :                                 OutputProcessor::Unit::ach,
    7746           5 :                                 state.dataSurface->ExtVentedCavity(Item).PassiveACH,
    7747             :                                 OutputProcessor::SOVTimeStepType::System,
    7748             :                                 OutputProcessor::SOVStoreType::Average,
    7749          10 :                                 state.dataSurface->ExtVentedCavity(Item).Name);
    7750          20 :             SetupOutputVariable(state,
    7751             :                                 "Surface Exterior Cavity Total Natural Ventilation Mass Flow Rate",
    7752             :                                 OutputProcessor::Unit::kg_s,
    7753           5 :                                 state.dataSurface->ExtVentedCavity(Item).PassiveMdotVent,
    7754             :                                 OutputProcessor::SOVTimeStepType::System,
    7755             :                                 OutputProcessor::SOVStoreType::Average,
    7756          10 :                                 state.dataSurface->ExtVentedCavity(Item).Name);
    7757          20 :             SetupOutputVariable(state,
    7758             :                                 "Surface Exterior Cavity Natural Ventilation from Wind Mass Flow Rate",
    7759             :                                 OutputProcessor::Unit::kg_s,
    7760           5 :                                 state.dataSurface->ExtVentedCavity(Item).PassiveMdotWind,
    7761             :                                 OutputProcessor::SOVTimeStepType::System,
    7762             :                                 OutputProcessor::SOVStoreType::Average,
    7763          10 :                                 state.dataSurface->ExtVentedCavity(Item).Name);
    7764          20 :             SetupOutputVariable(state,
    7765             :                                 "Surface Exterior Cavity Natural Ventilation from Buoyancy Mass Flow Rate",
    7766             :                                 OutputProcessor::Unit::kg_s,
    7767           5 :                                 state.dataSurface->ExtVentedCavity(Item).PassiveMdotTherm,
    7768             :                                 OutputProcessor::SOVTimeStepType::System,
    7769             :                                 OutputProcessor::SOVStoreType::Average,
    7770          10 :                                 state.dataSurface->ExtVentedCavity(Item).Name);
    7771             :         }
    7772         771 :     }
    7773             : 
    7774         771 :     void ExposedFoundationPerimeter::getData(EnergyPlusData &state, bool &ErrorsFound)
    7775             :     {
    7776             : 
    7777             :         int IOStatus; // Used in GetObjectItem
    7778             :         int NumAlphas;
    7779             :         int NumNumbers;
    7780             : 
    7781         771 :         auto const tolerance = 1e-6;
    7782             : 
    7783        1542 :         std::string cCurrentModuleObject = "SurfaceProperty:ExposedFoundationPerimeter";
    7784         771 :         int numObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7785             : 
    7786         794 :         for (int obj = 1; obj <= numObjects; ++obj) {
    7787          23 :             int alpF = 1;
    7788          23 :             int numF = 1;
    7789         161 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7790             :                                                                      cCurrentModuleObject,
    7791             :                                                                      obj,
    7792          23 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7793             :                                                                      NumAlphas,
    7794          23 :                                                                      state.dataIPShortCut->rNumericArgs,
    7795             :                                                                      NumNumbers,
    7796             :                                                                      IOStatus,
    7797          23 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7798          23 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7799          23 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7800          23 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7801             :             int Found =
    7802          23 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7803          23 :             if (Found == 0) {
    7804           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface");
    7805           0 :                 ErrorsFound = true;
    7806             :             }
    7807          23 :             alpF++;
    7808          23 :             if (state.dataSurface->Surface(Found).Class != SurfaceClass::Floor) {
    7809           0 :                 ShowWarningError(state, cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", surface is not a floor surface");
    7810           0 :                 ShowContinueError(state, cCurrentModuleObject + " will not be used");
    7811           0 :                 continue;
    7812             :             }
    7813             : 
    7814             :             // Choose calculation method
    7815          46 :             std::string calculationMethod = state.dataIPShortCut->cAlphaArgs(alpF);
    7816          23 :             if (calculationMethod != "TOTALEXPOSEDPERIMETER" && calculationMethod != "EXPOSEDPERIMETERFRACTION" && calculationMethod != "BYSEGMENT") {
    7817           0 :                 ShowSevereError(state,
    7818           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " + calculationMethod +
    7819           0 :                                     " is not a valid choice for " + state.dataIPShortCut->cAlphaFieldNames(alpF));
    7820           0 :                 ErrorsFound = true;
    7821             :             }
    7822          23 :             alpF++;
    7823             : 
    7824          46 :             Data data;
    7825          23 :             data.useDetailedExposedPerimeter = true;
    7826             : 
    7827          23 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
    7828           1 :                 if (calculationMethod == "TOTALEXPOSEDPERIMETER") {
    7829           1 :                     data.exposedFraction = state.dataIPShortCut->rNumericArgs(numF) / state.dataSurface->Surface(Found).Perimeter;
    7830           1 :                     if (data.exposedFraction > 1 + tolerance) {
    7831           0 :                         ShowWarningError(state,
    7832           0 :                                          cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " +
    7833           0 :                                              state.dataIPShortCut->cNumericFieldNames(numF) + " is greater than the perimeter of " +
    7834           0 :                                              state.dataSurface->Surface(Found).Name);
    7835           0 :                         ShowContinueError(state,
    7836           0 :                                           format("{} perimeter = {}, {} exposed perimeter = {}",
    7837           0 :                                                  state.dataSurface->Surface(Found).Name,
    7838           0 :                                                  state.dataSurface->Surface(Found).Perimeter,
    7839             :                                                  cCurrentModuleObject,
    7840           0 :                                                  state.dataIPShortCut->rNumericArgs(numF)));
    7841           0 :                         ShowContinueError(state,
    7842           0 :                                           state.dataIPShortCut->cNumericFieldNames(numF) + " will be set equal to " +
    7843           0 :                                               state.dataSurface->Surface(Found).Name + " perimeter");
    7844           0 :                         data.exposedFraction = 1.0;
    7845             :                     }
    7846             : 
    7847           1 :                     data.useDetailedExposedPerimeter = false;
    7848             :                 } else {
    7849           0 :                     ShowWarningError(state,
    7850           0 :                                      cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
    7851           0 :                                          " set as calculation method, but a value has been set for " +
    7852           0 :                                          state.dataIPShortCut->cNumericFieldNames(numF) + ". This value will be ignored.");
    7853             :                 }
    7854             :             } else {
    7855          22 :                 if (calculationMethod == "TOTALEXPOSEDPERIMETER") {
    7856           0 :                     ShowSevereError(state,
    7857           0 :                                     cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
    7858           0 :                                         " set as calculation method, but no value has been set for " +
    7859           0 :                                         state.dataIPShortCut->cNumericFieldNames(numF));
    7860           0 :                     ErrorsFound = true;
    7861             :                 }
    7862             :             }
    7863          23 :             numF++;
    7864             : 
    7865          23 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
    7866           3 :                 if (calculationMethod == "EXPOSEDPERIMETERFRACTION") {
    7867           3 :                     data.exposedFraction = state.dataIPShortCut->rNumericArgs(numF);
    7868           3 :                     data.useDetailedExposedPerimeter = false;
    7869             :                 } else {
    7870           0 :                     ShowWarningError(state,
    7871           0 :                                      cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
    7872           0 :                                          " set as calculation method, but a value has been set for " +
    7873           0 :                                          state.dataIPShortCut->cNumericFieldNames(numF) + ". This value will be ignored.");
    7874             :                 }
    7875             :             } else {
    7876          20 :                 if (calculationMethod == "EXPOSEDPERIMETERFRACTION") {
    7877           0 :                     ShowSevereError(state,
    7878           0 :                                     cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
    7879           0 :                                         " set as calculation method, but no value has been set for " +
    7880           0 :                                         state.dataIPShortCut->cNumericFieldNames(numF));
    7881           0 :                     ErrorsFound = true;
    7882             :                 }
    7883             :             }
    7884          23 :             numF++;
    7885             : 
    7886          23 :             int numRemainingFields = NumAlphas - (alpF - 1) + NumNumbers - (numF - 1);
    7887          23 :             if (numRemainingFields > 0) {
    7888          19 :                 if (calculationMethod == "BYSEGMENT") {
    7889          19 :                     if (numRemainingFields != (int)state.dataSurface->Surface(Found).Vertex.size()) {
    7890           0 :                         ShowSevereError(state,
    7891           0 :                                         cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name +
    7892           0 :                                             ", must have equal number of segments as the floor has vertices." +
    7893           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) + "\" and \"" +
    7894           0 :                                             state.dataIPShortCut->cNumericFieldNames(numF - 1) + "\"");
    7895           0 :                         ShowContinueError(state,
    7896           0 :                                           format("{} number of vertices = {}, {} number of segments = {}",
    7897           0 :                                                  state.dataSurface->Surface(Found).Name,
    7898           0 :                                                  state.dataSurface->Surface(Found).Vertex.size(),
    7899             :                                                  cCurrentModuleObject,
    7900           0 :                                                  numRemainingFields));
    7901           0 :                         ErrorsFound = true;
    7902             :                     }
    7903          95 :                     for (int segNum = 0; segNum < numRemainingFields; segNum++) {
    7904          76 :                         if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "YES")) {
    7905          28 :                             data.isExposedPerimeter.push_back(true);
    7906          48 :                         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "NO")) {
    7907          48 :                             data.isExposedPerimeter.push_back(false);
    7908           0 :                         } else if (state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
    7909           0 :                             ShowSevereError(state,
    7910           0 :                                             cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
    7911           0 :                                                 " set as calculation method, but no value has been set for " +
    7912           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(alpF) + ". Must be \"Yes\" or \"No\".");
    7913           0 :                             ErrorsFound = true;
    7914             :                         } else {
    7915           0 :                             ShowSevereError(state,
    7916           0 :                                             cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " +
    7917           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(alpF) + " invalid [" + state.dataIPShortCut->cAlphaArgs(alpF) +
    7918             :                                                 "]. Must be \"Yes\" or \"No\".");
    7919           0 :                             ErrorsFound = true;
    7920             :                         }
    7921          76 :                         alpF++;
    7922             :                     }
    7923             :                 }
    7924             :             } else {
    7925           4 :                 if (calculationMethod == "BYSEGMENT") {
    7926           0 :                     ShowSevereError(state,
    7927           0 :                                     cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
    7928             :                                         " set as calculation method, but no values have been set for Surface Segments Exposed");
    7929           0 :                     ErrorsFound = true;
    7930             :                 }
    7931             :             }
    7932          23 :             surfaceMap[Found] = data;
    7933             :         }
    7934         771 :     }
    7935             : 
    7936         771 :     void GetSurfaceLocalEnvData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    7937             :     {
    7938             :         // SUBROUTINE INFORMATION:
    7939             :         //       AUTHOR         X LUO
    7940             :         //       DATE WRITTEN   July 2017
    7941             :         //       MODIFIED       na
    7942             :         //       RE-ENGINEERED  na
    7943             : 
    7944             :         // PURPOSE OF THIS SUBROUTINE:
    7945             :         // load input data for Outdoor Air Node for exterior surfaces
    7946             : 
    7947             :         // Using/Aliasing
    7948             :         using namespace DataErrorTracking;
    7949             :         using DataLoopNode::ObjectIsParent;
    7950             :         using NodeInputManager::GetOnlySingleNode;
    7951             :         using OutAirNodeManager::CheckOutAirNodeNumber;
    7952             :         using ScheduleManager::GetScheduleIndex;
    7953             : 
    7954             :         // SUBROUTINE PARAMETER DEFINITIONS:
    7955             :         static constexpr std::string_view RoutineName("GetSurfaceLocalEnvData: ");
    7956             : 
    7957             :         // INTERFACE BLOCK SPECIFICATIONS:na
    7958             :         // DERIVED TYPE DEFINITIONS:na
    7959             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7960             :         int NumAlpha;
    7961             :         int NumNumeric;
    7962             :         int IOStat;
    7963             : 
    7964             :         //-----------------------------------------------------------------------
    7965             :         //                SurfaceProperty:LocalEnvironment
    7966             :         //-----------------------------------------------------------------------
    7967         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7968         771 :         cCurrentModuleObject = "SurfaceProperty:LocalEnvironment";
    7969         771 :         state.dataSurface->TotSurfLocalEnv = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7970             : 
    7971         771 :         if (state.dataSurface->TotSurfLocalEnv > 0) {
    7972             : 
    7973           4 :             state.dataGlobal->AnyLocalEnvironmentsInModel = true;
    7974             : 
    7975           4 :             if (!allocated(state.dataSurface->SurfLocalEnvironment)) {
    7976           4 :                 state.dataSurface->SurfLocalEnvironment.allocate(state.dataSurface->TotSurfLocalEnv);
    7977             :             }
    7978             : 
    7979         126 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfLocalEnv; ++Loop) {
    7980             : 
    7981         122 :                 auto &SurfLocalEnv = state.dataSurface->SurfLocalEnvironment(Loop);
    7982             : 
    7983         854 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7984             :                                                                          cCurrentModuleObject,
    7985             :                                                                          Loop,
    7986         122 :                                                                          state.dataIPShortCut->cAlphaArgs,
    7987             :                                                                          NumAlpha,
    7988         122 :                                                                          state.dataIPShortCut->rNumericArgs,
    7989             :                                                                          NumNumeric,
    7990             :                                                                          IOStat,
    7991         122 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    7992         122 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    7993         122 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    7994         122 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    7995         122 :                 UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    7996             : 
    7997         122 :                 SurfLocalEnv.Name = state.dataIPShortCut->cAlphaArgs(1);
    7998             : 
    7999             :                 // Assign surface number
    8000         122 :                 int SurfNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface);
    8001         122 :                 if (SurfNum == 0) {
    8002           0 :                     ShowSevereError(state,
    8003           0 :                                     format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8004             :                                            RoutineName,
    8005             :                                            cCurrentModuleObject,
    8006             :                                            SurfLocalEnv.Name,
    8007           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2)));
    8008           0 :                     ShowContinueError(state,
    8009           0 :                                       format("{} entered value = \"{}\", no corresponding surface (ref BuildingSurface:Detailed) has been "
    8010             :                                              "found in the input file.",
    8011           0 :                                              state.dataIPShortCut->cAlphaFieldNames(2),
    8012           0 :                                              state.dataIPShortCut->cAlphaArgs(2)));
    8013           0 :                     ErrorsFound = true;
    8014             :                 } else {
    8015         122 :                     SurfLocalEnv.SurfPtr = SurfNum;
    8016             :                 }
    8017             : 
    8018             :                 // Assign External Shading Schedule number
    8019         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    8020         102 :                     int ExtShadingSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    8021         102 :                     if (ExtShadingSchedNum == 0) {
    8022           0 :                         ShowSevereError(state,
    8023           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8024             :                                                RoutineName,
    8025             :                                                cCurrentModuleObject,
    8026             :                                                SurfLocalEnv.Name,
    8027           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3)));
    8028           0 :                         ShowContinueError(state,
    8029           0 :                                           format("{} entered value = \"{}\", no corresponding shading schedule has been found in the input file.",
    8030           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(3),
    8031           0 :                                                  state.dataIPShortCut->cAlphaArgs(3)));
    8032           0 :                         ErrorsFound = true;
    8033             :                     } else {
    8034         102 :                         SurfLocalEnv.ExtShadingSchedPtr = ExtShadingSchedNum;
    8035             :                     }
    8036             :                 }
    8037             : 
    8038             :                 // Assign surrounding surfaces object number;
    8039         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    8040             :                     int SurroundingSurfsNum =
    8041           6 :                         UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataSurface->SurroundingSurfsProperty);
    8042           6 :                     if (SurroundingSurfsNum == 0) {
    8043           0 :                         ShowSevereError(state,
    8044           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8045             :                                                RoutineName,
    8046             :                                                cCurrentModuleObject,
    8047             :                                                SurfLocalEnv.Name,
    8048           0 :                                                state.dataIPShortCut->cAlphaFieldNames(4)));
    8049           0 :                         ShowContinueError(state,
    8050           0 :                                           format("{} entered value = \"{}\", no corresponding surrounding surfaces properties has been found "
    8051             :                                                  "in the input file.",
    8052           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(4),
    8053           0 :                                                  state.dataIPShortCut->cAlphaArgs(4)));
    8054           0 :                         ErrorsFound = true;
    8055             :                     } else {
    8056           6 :                         SurfLocalEnv.SurroundingSurfsPtr = SurroundingSurfsNum;
    8057             :                     }
    8058             :                 }
    8059             : 
    8060             :                 // Assign outdoor air node number;
    8061         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    8062           4 :                     int NodeNum = GetOnlySingleNode(state,
    8063           2 :                                                     state.dataIPShortCut->cAlphaArgs(5),
    8064             :                                                     ErrorsFound,
    8065             :                                                     DataLoopNode::ConnectionObjectType::SurfacePropertyLocalEnvironment,
    8066             :                                                     SurfLocalEnv.Name,
    8067             :                                                     DataLoopNode::NodeFluidType::Air,
    8068             :                                                     DataLoopNode::ConnectionType::Inlet,
    8069             :                                                     NodeInputManager::CompFluidStream::Primary,
    8070           4 :                                                     ObjectIsParent);
    8071           2 :                     if (NodeNum == 0 && CheckOutAirNodeNumber(state, NodeNum)) {
    8072           0 :                         ShowSevereError(state,
    8073           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8074             :                                                RoutineName,
    8075             :                                                cCurrentModuleObject,
    8076             :                                                SurfLocalEnv.Name,
    8077           0 :                                                state.dataIPShortCut->cAlphaFieldNames(5)));
    8078           0 :                         ShowContinueError(state,
    8079           0 :                                           format("{} entered value = \"{}\", no corresponding outdoor air node has been found in the input file.",
    8080           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(5),
    8081           0 :                                                  state.dataIPShortCut->cAlphaArgs(5)));
    8082           0 :                         ErrorsFound = true;
    8083             :                     } else {
    8084           2 :                         SurfLocalEnv.OutdoorAirNodePtr = NodeNum;
    8085             :                     }
    8086             :                 }
    8087             : 
    8088             :                 // get ground surfaces object number;
    8089         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) {
    8090          13 :                     int GndSurfsNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(6), state.dataSurface->GroundSurfsProperty);
    8091          13 :                     if (GndSurfsNum == 0) {
    8092           0 :                         ShowSevereError(state,
    8093           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8094             :                                                RoutineName,
    8095             :                                                cCurrentModuleObject,
    8096             :                                                SurfLocalEnv.Name,
    8097           0 :                                                state.dataIPShortCut->cAlphaFieldNames(6)));
    8098           0 :                         ShowContinueError(
    8099             :                             state,
    8100           0 :                             format("{} entered value = \"{}\", no corresponding ground surfaces object has been found in the input file.",
    8101           0 :                                    state.dataIPShortCut->cAlphaFieldNames(6),
    8102           0 :                                    state.dataIPShortCut->cAlphaArgs(6)));
    8103           0 :                         ErrorsFound = true;
    8104             :                     } else {
    8105          13 :                         SurfLocalEnv.GroundSurfsPtr = GndSurfsNum;
    8106             :                     }
    8107             :                 }
    8108             :             }
    8109             :         }
    8110             :         // Link surface properties to surface object
    8111       44533 :         for (int SurfLoop = 1; SurfLoop <= state.dataSurface->TotSurfaces; ++SurfLoop) {
    8112       57268 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfLocalEnv; ++Loop) {
    8113       13506 :                 auto &SurfLocalEnv = state.dataSurface->SurfLocalEnvironment(Loop);
    8114       13506 :                 if (SurfLocalEnv.SurfPtr == SurfLoop) {
    8115         122 :                     auto &surface = state.dataSurface->Surface(SurfLoop);
    8116         122 :                     if (SurfLocalEnv.OutdoorAirNodePtr != 0) {
    8117           2 :                         surface.SurfLinkedOutAirNode = SurfLocalEnv.OutdoorAirNodePtr;
    8118             :                     }
    8119         122 :                     if (SurfLocalEnv.ExtShadingSchedPtr != 0) {
    8120         102 :                         surface.SurfSchedExternalShadingFrac = true;
    8121         102 :                         surface.SurfExternalShadingSchInd = SurfLocalEnv.ExtShadingSchedPtr;
    8122             :                     }
    8123         122 :                     if (SurfLocalEnv.SurroundingSurfsPtr != 0) {
    8124           6 :                         surface.SurfHasSurroundingSurfProperty = true;
    8125           6 :                         surface.SurfSurroundingSurfacesNum = SurfLocalEnv.SurroundingSurfsPtr;
    8126             :                     }
    8127         122 :                     if (SurfLocalEnv.GroundSurfsPtr != 0) {
    8128          13 :                         surface.IsSurfPropertyGndSurfacesDefined = true;
    8129          13 :                         surface.UseSurfPropertyGndSurfTemp = true;
    8130          13 :                         surface.UseSurfPropertyGndSurfRefl = true;
    8131          13 :                         surface.SurfPropertyGndSurfIndex = SurfLocalEnv.GroundSurfsPtr;
    8132             :                     }
    8133             :                 }
    8134             :             }
    8135             :         }
    8136         771 :     }
    8137             : 
    8138         771 :     void GetSurfaceSrdSurfsData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    8139             :     {
    8140             :         // SUBROUTINE INFORMATION:
    8141             :         //       AUTHOR         X LUO
    8142             :         //       DATE WRITTEN   July 2017
    8143             :         //       MODIFIED       na
    8144             :         //       RE-ENGINEERED  na
    8145             : 
    8146             :         // PURPOSE OF THIS SUBROUTINE:
    8147             :         // load input data for surrounding surfaces properties for exterior surfaces
    8148             : 
    8149             :         // Using/Aliasing
    8150             :         using namespace DataErrorTracking;
    8151             :         using DataLoopNode::ObjectIsParent;
    8152             :         using NodeInputManager::GetOnlySingleNode;
    8153             :         using OutAirNodeManager::CheckOutAirNodeNumber;
    8154             :         using ScheduleManager::GetScheduleIndex;
    8155             : 
    8156             :         // INTERFACE BLOCK SPECIFICATIONS:na
    8157             :         // DERIVED TYPE DEFINITIONS:na
    8158             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8159             :         int NumAlpha;
    8160             :         int NumNumeric;
    8161             :         int IOStat;
    8162             :         int TotSrdSurfProperties;
    8163             : 
    8164             :         //-----------------------------------------------------------------------
    8165             :         //                SurfaceProperty:SurroundingSurfaces
    8166             :         //-----------------------------------------------------------------------
    8167         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    8168         771 :         cCurrentModuleObject = "SurfaceProperty:SurroundingSurfaces";
    8169         771 :         TotSrdSurfProperties = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8170             : 
    8171         771 :         if (TotSrdSurfProperties > 0) {
    8172             : 
    8173           2 :             if (!allocated(state.dataSurface->SurroundingSurfsProperty)) {
    8174           2 :                 state.dataSurface->SurroundingSurfsProperty.allocate(TotSrdSurfProperties);
    8175             :             }
    8176             : 
    8177           8 :             for (int Loop = 1; Loop <= TotSrdSurfProperties; ++Loop) {
    8178             : 
    8179           6 :                 auto &SrdSurfsProp = state.dataSurface->SurroundingSurfsProperty(Loop);
    8180             : 
    8181          42 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8182             :                                                                          cCurrentModuleObject,
    8183             :                                                                          Loop,
    8184           6 :                                                                          state.dataIPShortCut->cAlphaArgs,
    8185             :                                                                          NumAlpha,
    8186           6 :                                                                          state.dataIPShortCut->rNumericArgs,
    8187             :                                                                          NumNumeric,
    8188             :                                                                          IOStat,
    8189           6 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    8190           6 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    8191           6 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    8192           6 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    8193           6 :                 UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    8194             : 
    8195             :                 // A1: Name
    8196           6 :                 SrdSurfsProp.Name = state.dataIPShortCut->cAlphaArgs(1);
    8197             : 
    8198             :                 // N1: sky view factor
    8199           6 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(1)) {
    8200           6 :                     SrdSurfsProp.SkyViewFactor = state.dataIPShortCut->rNumericArgs(1);
    8201           6 :                     SrdSurfsProp.IsSkyViewFactorSet = true;
    8202             :                 }
    8203             : 
    8204             :                 // A2: sky temp sch name
    8205           6 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    8206           0 :                     SrdSurfsProp.SkyTempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    8207             :                 }
    8208             : 
    8209             :                 // N2: ground view factor
    8210           6 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
    8211           3 :                     SrdSurfsProp.GroundViewFactor = state.dataIPShortCut->rNumericArgs(2);
    8212           3 :                     SrdSurfsProp.IsGroundViewFactorSet = true;
    8213             :                 }
    8214             : 
    8215             :                 // A3: ground temp sch name
    8216           6 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    8217           0 :                     SrdSurfsProp.GroundTempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    8218             :                 }
    8219             : 
    8220             :                 // The object requires at least one srd surface input, each surface requires a set of 3 fields (2 Alpha fields Name and Temp
    8221             :                 // Sch Name and 1 Num fields View Factor)
    8222           6 :                 if (NumAlpha < 5) {
    8223           0 :                     ShowSevereError(state, format("{} = \"{}\" is not defined correctly.", cCurrentModuleObject, SrdSurfsProp.Name));
    8224           0 :                     ShowContinueError(state, "At lease one set of surrounding surface properties should be defined.");
    8225           0 :                     ErrorsFound = true;
    8226           0 :                     continue;
    8227             :                 }
    8228           6 :                 if ((NumAlpha - 3) / 2 != (NumNumeric - 2)) {
    8229           0 :                     ShowSevereError(state, format("{} = \"{}\" is not defined correctly.", cCurrentModuleObject, SrdSurfsProp.Name));
    8230           0 :                     ShowContinueError(state, "Check number of input fields for each surrounding surface.");
    8231           0 :                     ErrorsFound = true;
    8232           0 :                     continue;
    8233             :                 }
    8234             :                 // Read surrounding surfaces properties
    8235           6 :                 SrdSurfsProp.TotSurroundingSurface = NumNumeric - 1;
    8236           6 :                 SrdSurfsProp.SurroundingSurfs.allocate(SrdSurfsProp.TotSurroundingSurface);
    8237          20 :                 for (int SurfLoop = 1; SurfLoop <= SrdSurfsProp.TotSurroundingSurface; ++SurfLoop) {
    8238          14 :                     SrdSurfsProp.SurroundingSurfs(SurfLoop).Name = state.dataIPShortCut->cAlphaArgs(SurfLoop * 2 + 2);
    8239          14 :                     SrdSurfsProp.SurroundingSurfs(SurfLoop).ViewFactor = state.dataIPShortCut->rNumericArgs(SurfLoop + 2);
    8240          14 :                     SrdSurfsProp.SurroundingSurfs(SurfLoop).TempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(SurfLoop * 2 + 3));
    8241             :                 }
    8242             :             }
    8243             :         }
    8244         771 :     }
    8245             : 
    8246         771 :     void GetSurfaceGroundSurfsData(EnergyPlusData &state, bool &ErrorsFound)
    8247             :     {
    8248             : 
    8249         772 :         std::string cCurrentModuleObject = "SurfaceProperty:GroundSurfaces";
    8250         771 :         state.dataSurface->TotSurfPropGndSurfs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8251         772 :         auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
    8252         771 :         if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
    8253         770 :             if (state.dataSurface->TotSurfPropGndSurfs > 0) ErrorsFound = true;
    8254         770 :             return;
    8255             :         } else {
    8256           1 :             auto &instancesValue = instances.value();
    8257           6 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    8258           5 :                 auto const &fields = instance.value();
    8259           5 :                 auto const &thisObjectName = instance.key();
    8260          10 :                 GroundSurfacesProperty thisGndSurfsObj;
    8261           5 :                 thisGndSurfsObj.Name = UtilityRoutines::MakeUPPERCase(thisObjectName);
    8262           5 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
    8263          10 :                 auto groundSurfaces = fields.find("ground_surfaces");
    8264           5 :                 if (groundSurfaces != fields.end()) {
    8265          10 :                     auto groundSurfacesArray = groundSurfaces.value();
    8266           5 :                     thisGndSurfsObj.NumGndSurfs = groundSurfacesArray.size();
    8267          16 :                     for (auto groundSurface : groundSurfacesArray) {
    8268          22 :                         GroundSurfacesData thisGndSurf;
    8269          22 :                         auto GndSurfName = groundSurface.find("ground_surface_name");
    8270          11 :                         if (GndSurfName != groundSurface.end()) {
    8271          22 :                             auto ground_surf_name = groundSurface.at("ground_surface_name").get<std::string>();
    8272          11 :                             if (!ground_surf_name.empty()) {
    8273          11 :                                 thisGndSurf.Name = EnergyPlus::UtilityRoutines::MakeUPPERCase(ground_surf_name);
    8274             :                             }
    8275             :                         }
    8276          22 :                         auto groundSurfViewFactor = groundSurface.find("ground_surface_view_factor");
    8277          11 :                         if (groundSurfViewFactor != groundSurface.end()) {
    8278          11 :                             thisGndSurf.ViewFactor = groundSurface.at("ground_surface_view_factor").get<Real64>();
    8279          11 :                             thisGndSurfsObj.IsGroundViewFactorSet = true;
    8280             :                         }
    8281          22 :                         auto TempSchName = groundSurface.find("ground_surface_temperature_schedule_name");
    8282          11 :                         if (TempSchName != groundSurface.end()) {
    8283          20 :                             auto gnd_surf_TempSchName = groundSurface.at("ground_surface_temperature_schedule_name").get<std::string>();
    8284          10 :                             if (!gnd_surf_TempSchName.empty()) {
    8285          10 :                                 thisGndSurf.TempSchPtr =
    8286          20 :                                     ScheduleManager::GetScheduleIndex(state, EnergyPlus::UtilityRoutines::MakeUPPERCase(gnd_surf_TempSchName));
    8287             :                             }
    8288             :                         }
    8289          22 :                         auto ReflSchName = groundSurface.find("ground_surface_reflectance_schedule_name");
    8290          11 :                         if (ReflSchName != groundSurface.end()) {
    8291          20 :                             auto gnd_surf_ReflSchName = groundSurface.at("ground_surface_reflectance_schedule_name").get<std::string>();
    8292          10 :                             if (!gnd_surf_ReflSchName.empty()) {
    8293          10 :                                 thisGndSurf.ReflSchPtr =
    8294          20 :                                     ScheduleManager::GetScheduleIndex(state, EnergyPlus::UtilityRoutines::MakeUPPERCase(gnd_surf_ReflSchName));
    8295             :                             }
    8296             :                         }
    8297          11 :                         thisGndSurfsObj.GndSurfs.push_back(thisGndSurf);
    8298             :                     }
    8299             :                 }
    8300          16 :                 for (int gSurfNum = 1; gSurfNum <= thisGndSurfsObj.NumGndSurfs; gSurfNum++) {
    8301          11 :                     thisGndSurfsObj.SurfsViewFactorSum += thisGndSurfsObj.GndSurfs(gSurfNum).ViewFactor;
    8302             :                 }
    8303           5 :                 state.dataSurface->GroundSurfsProperty.push_back(thisGndSurfsObj);
    8304             :             }
    8305             :         }
    8306             :         // set report variables
    8307           1 :         if (state.dataSurface->TotSurfPropGndSurfs > 0) {
    8308           6 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfPropGndSurfs; Loop++) {
    8309           5 :                 bool SetTempSchReportVar = true;
    8310           5 :                 bool SetReflSchReportVar = true;
    8311           5 :                 auto &thisGndSurfsObj = state.dataSurface->GroundSurfsProperty(Loop);
    8312          16 :                 for (int gSurfNum = 1; gSurfNum <= thisGndSurfsObj.NumGndSurfs; gSurfNum++) {
    8313          11 :                     if (thisGndSurfsObj.GndSurfs(gSurfNum).TempSchPtr != 0 && SetTempSchReportVar) {
    8314           8 :                         SetupOutputVariable(state,
    8315             :                                             "Surfaces Property Ground Surfaces Average Temperature",
    8316             :                                             OutputProcessor::Unit::C,
    8317             :                                             thisGndSurfsObj.SurfsTempAvg,
    8318             :                                             OutputProcessor::SOVTimeStepType::Zone,
    8319             :                                             OutputProcessor::SOVStoreType::State,
    8320           4 :                                             thisGndSurfsObj.Name);
    8321           4 :                         SetTempSchReportVar = false;
    8322             :                     }
    8323          11 :                     if (thisGndSurfsObj.GndSurfs(gSurfNum).ReflSchPtr != 0 && SetReflSchReportVar) {
    8324           8 :                         SetupOutputVariable(state,
    8325             :                                             "Surfaces Property Ground Surfaces Average Reflectance",
    8326             :                                             OutputProcessor::Unit::None,
    8327             :                                             thisGndSurfsObj.SurfsReflAvg,
    8328             :                                             OutputProcessor::SOVTimeStepType::Zone,
    8329             :                                             OutputProcessor::SOVStoreType::State,
    8330           4 :                                             thisGndSurfsObj.Name);
    8331           4 :                         SetReflSchReportVar = false;
    8332             :                     }
    8333             :                 }
    8334             :             }
    8335             :         }
    8336             :     }
    8337             : 
    8338         771 :     void GetSurfaceHeatTransferAlgorithmOverrides(EnergyPlusData &state, bool &ErrorsFound)
    8339             :     {
    8340             : 
    8341             :         // SUBROUTINE INFORMATION:
    8342             :         //       AUTHOR         B. Griffith, portions from ApplyConvectionValue by Linda Lawrie
    8343             :         //       DATE WRITTEN   July 2012
    8344             :         //       MODIFIED       na
    8345             :         //       RE-ENGINEERED  na
    8346             : 
    8347             :         // PURPOSE OF THIS SUBROUTINE:
    8348             :         // <description>
    8349             : 
    8350             :         // Using/Aliasing
    8351             : 
    8352             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8353             :         int CountHTAlgoObjectsSingleSurf;
    8354             :         int CountHTAlgoObjectsMultiSurf;
    8355             :         int CountHTAlgoObjectsSurfList;
    8356             :         int IOStatus; // Used in GetObjectItem
    8357         771 :         bool ErrorsFoundSingleSurf(false);
    8358         771 :         bool ErrorsFoundMultiSurf(false);
    8359         771 :         bool ErrorsFoundSurfList(false);
    8360         771 :         bool ErrorsFoundByConstruct(false);
    8361             :         DataSurfaces::HeatTransferModel tmpAlgoInput;
    8362             :         int Item;
    8363             :         int Item1;
    8364             :         int NumAlphas;
    8365             :         int NumNumbers;
    8366             :         int Found;
    8367             :         bool SurfacesOfType;
    8368             :         int SurfNum;
    8369             :         //  INTEGER :: Index
    8370             :         int NumEMPDMat;
    8371             :         int NumPCMat;
    8372             :         int NumVTCMat;
    8373             :         int NumHAMTMat1;
    8374             :         int NumHAMTMat2;
    8375             :         int NumHAMTMat3;
    8376             :         int NumHAMTMat4;
    8377             :         int NumHAMTMat5;
    8378             :         int NumHAMTMat6;
    8379             :         int SumHAMTMat;
    8380             :         bool msgneeded;
    8381             : 
    8382         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    8383         771 :         cCurrentModuleObject = "SurfaceProperty:HeatBalanceSourceTerm";
    8384         771 :         int CountAddHeatSourceSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8385             : 
    8386         775 :         for (Item = 1; Item <= CountAddHeatSourceSurf; ++Item) {
    8387          28 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8388             :                                                                      cCurrentModuleObject,
    8389             :                                                                      Item,
    8390           4 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8391             :                                                                      NumAlphas,
    8392           4 :                                                                      state.dataIPShortCut->rNumericArgs,
    8393             :                                                                      NumNumbers,
    8394             :                                                                      IOStatus,
    8395           4 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8396           4 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8397           4 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8398           4 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8399           4 :             Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    8400             : 
    8401           4 :             if (Found == 0) {
    8402           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface.");
    8403           0 :                 ErrorsFound = true;
    8404           8 :             } else if (state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule ||
    8405           4 :                        state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule) {
    8406           0 :                 ShowSevereError(state,
    8407           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    8408             :                                     "\", multiple SurfaceProperty:HeatBalanceSourceTerm objects applied to the same surface.");
    8409           0 :                 ErrorsFound = true;
    8410             :             }
    8411             : 
    8412           4 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    8413           1 :                 state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule =
    8414           1 :                     EnergyPlus::ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    8415           1 :                 state.dataSurface->AnyHeatBalanceInsideSourceTerm = true;
    8416           1 :                 if (state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule == 0) {
    8417           0 :                     ShowSevereError(state,
    8418           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", cannot find the matching Schedule: " +
    8419           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    8420           0 :                     ErrorsFound = true;
    8421             :                 }
    8422             :             }
    8423             : 
    8424           4 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    8425           3 :                 state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule =
    8426           3 :                     EnergyPlus::ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    8427           3 :                 state.dataSurface->AnyHeatBalanceOutsideSourceTerm = true;
    8428           3 :                 if (state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule == 0) {
    8429           0 :                     ShowSevereError(state,
    8430           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", cannot find the matching Schedule: " +
    8431           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
    8432           0 :                     ErrorsFound = true;
    8433           3 :                 } else if (state.dataSurface->Surface(Found).OSCPtr > 0) {
    8434           0 :                     ShowSevereError(state,
    8435           0 :                                     cCurrentModuleObject +
    8436           0 :                                         "=\"SurfaceProperty:HeatBalanceSourceTerm\", cannot be specified for OtherSideCoefficient Surface=" +
    8437           0 :                                         state.dataIPShortCut->cAlphaArgs(1));
    8438           0 :                     ErrorsFound = true;
    8439             :                 }
    8440             :             }
    8441             : 
    8442           5 :             if (state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule == 0 &&
    8443           1 :                 state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule == 0) {
    8444           0 :                 ShowSevereError(state,
    8445           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    8446             :                                     "\", no schedule defined for additional heat source.");
    8447           0 :                 ErrorsFound = true;
    8448             :             }
    8449             :         }
    8450             : 
    8451             :         // first initialize each heat transfer surface with the overall model type, array assignment
    8452       44533 :         for (auto &e : state.dataSurface->Surface)
    8453       43762 :             e.HeatTransferAlgorithm = state.dataHeatBal->OverallHeatTransferSolutionAlgo;
    8454             : 
    8455         771 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm";
    8456         771 :         CountHTAlgoObjectsSingleSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8457             : 
    8458         771 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm";
    8459         773 :         for (Item = 1; Item <= CountHTAlgoObjectsSingleSurf; ++Item) {
    8460          14 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8461             :                                                                      cCurrentModuleObject,
    8462             :                                                                      Item,
    8463           2 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8464             :                                                                      NumAlphas,
    8465           2 :                                                                      state.dataIPShortCut->rNumericArgs,
    8466             :                                                                      NumNumbers,
    8467             :                                                                      IOStatus,
    8468           2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8469           2 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8470           2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8471           2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8472           2 :             ErrorsFoundSingleSurf = false;
    8473           2 :             Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    8474             : 
    8475           2 :             if (Found == 0) {
    8476           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface.");
    8477           0 :                 ErrorsFoundSingleSurf = true;
    8478             :             }
    8479             : 
    8480             :             {
    8481           4 :                 auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
    8482             : 
    8483           2 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8484           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8485           0 :                     state.dataHeatBal->AnyCTF = true;
    8486           2 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8487           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8488           1 :                     state.dataHeatBal->AnyEMPD = true;
    8489           1 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8490           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8491           0 :                     state.dataHeatBal->AnyHAMT = true;
    8492           1 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8493           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8494           1 :                     state.dataHeatBal->AnyCondFD = true;
    8495             :                 } else {
    8496           0 :                     ShowSevereError(state,
    8497           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    8498           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    8499           0 :                     ErrorsFoundSingleSurf = true;
    8500             :                 }
    8501             :             }
    8502             : 
    8503           2 :             if (!ErrorsFoundSingleSurf) {
    8504           2 :                 state.dataSurface->Surface(Found).HeatTransferAlgorithm = tmpAlgoInput;
    8505             :             } else {
    8506           0 :                 ErrorsFound = true;
    8507             :             }
    8508             :         } // single surface heat transfer algorithm override
    8509             : 
    8510         771 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:MultipleSurface";
    8511         771 :         CountHTAlgoObjectsMultiSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8512             : 
    8513         771 :         for (Item = 1; Item <= CountHTAlgoObjectsMultiSurf; ++Item) {
    8514           0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8515             :                                                                      cCurrentModuleObject,
    8516             :                                                                      Item,
    8517           0 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8518             :                                                                      NumAlphas,
    8519           0 :                                                                      state.dataIPShortCut->rNumericArgs,
    8520             :                                                                      NumNumbers,
    8521             :                                                                      IOStatus,
    8522           0 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8523           0 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8524           0 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8525           0 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8526           0 :             ErrorsFoundMultiSurf = false;
    8527             :             {
    8528           0 :                 auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(3));
    8529             : 
    8530           0 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8531           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8532           0 :                     state.dataHeatBal->AnyCTF = true;
    8533           0 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8534           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8535           0 :                     state.dataHeatBal->AnyEMPD = true;
    8536           0 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8537           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8538           0 :                     state.dataHeatBal->AnyHAMT = true;
    8539           0 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8540           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8541           0 :                     state.dataHeatBal->AnyCondFD = true;
    8542             :                 } else {
    8543           0 :                     ShowSevereError(state,
    8544           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    8545           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
    8546           0 :                     ErrorsFoundMultiSurf = true;
    8547             :                 }
    8548             :             }
    8549             : 
    8550             :             {
    8551           0 :                 auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
    8552             : 
    8553           0 :                 if (SELECT_CASE_var == "ALLEXTERIORSURFACES") {
    8554           0 :                     SurfacesOfType = false;
    8555           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8556           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8557           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
    8558           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8559           0 :                         SurfacesOfType = true;
    8560           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8561             :                     }
    8562             : 
    8563           0 :                 } else if (SELECT_CASE_var == "ALLEXTERIORWALLS") {
    8564           0 :                     SurfacesOfType = false;
    8565           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8566           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8567           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
    8568             : 
    8569           0 :                         if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) continue;
    8570           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8571           0 :                         SurfacesOfType = true;
    8572           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8573             :                     }
    8574             : 
    8575           0 :                 } else if (SELECT_CASE_var == "ALLEXTERIORROOFS") {
    8576           0 :                     SurfacesOfType = false;
    8577           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8578           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8579           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
    8580           0 :                         if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof) continue;
    8581           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8582           0 :                         SurfacesOfType = true;
    8583           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8584             :                     }
    8585             : 
    8586           0 :                 } else if (SELECT_CASE_var == "ALLEXTERIORFLOORS") {
    8587           0 :                     SurfacesOfType = false;
    8588           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8589           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8590           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
    8591           0 :                         if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) continue;
    8592           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8593           0 :                         SurfacesOfType = true;
    8594           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8595             :                     }
    8596             : 
    8597           0 :                 } else if (SELECT_CASE_var == "ALLGROUNDCONTACTSURFACES") {
    8598           0 :                     SurfacesOfType = false;
    8599           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8600           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8601           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond != Ground) continue; // ground BC
    8602           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8603           0 :                         SurfacesOfType = true;
    8604           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8605             :                     }
    8606           0 :                 } else if (SELECT_CASE_var == "ALLINTERIORSURFACES") {
    8607           0 :                     SurfacesOfType = false;
    8608           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8609           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8610           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
    8611           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8612           0 :                         SurfacesOfType = true;
    8613           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8614             :                     }
    8615             : 
    8616           0 :                 } else if (SELECT_CASE_var == "ALLINTERIORWALLS") {
    8617           0 :                     SurfacesOfType = false;
    8618           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8619           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8620           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
    8621           0 :                         if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) continue;
    8622           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8623           0 :                         SurfacesOfType = true;
    8624           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8625             :                     }
    8626             : 
    8627           0 :                 } else if ((SELECT_CASE_var == "ALLINTERIORROOFS") || (SELECT_CASE_var == "ALLINTERIORCEILINGS")) {
    8628           0 :                     SurfacesOfType = false;
    8629           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8630           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8631           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
    8632           0 :                         if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof) continue;
    8633           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8634           0 :                         SurfacesOfType = true;
    8635           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8636             :                     }
    8637             : 
    8638           0 :                 } else if (SELECT_CASE_var == "ALLINTERIORFLOORS") {
    8639           0 :                     SurfacesOfType = false;
    8640           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8641           0 :                         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    8642           0 :                         if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
    8643           0 :                         if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) continue;
    8644           0 :                         if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
    8645           0 :                         SurfacesOfType = true;
    8646           0 :                         state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
    8647             :                     }
    8648             :                 } else {
    8649           0 :                     SurfacesOfType = false;
    8650           0 :                     ShowSevereError(state,
    8651           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    8652           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    8653           0 :                     ErrorsFoundMultiSurf = true;
    8654             :                 }
    8655             :             }
    8656             : 
    8657           0 :             if (!SurfacesOfType) {
    8658           0 :                 ShowWarningError(state,
    8659           0 :                                  "In " + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    8660           0 :                                      "\", for Multiple Surface Assignment=\"" + state.dataIPShortCut->cAlphaArgs(2) +
    8661             :                                      "\", there were no surfaces of that type found for assignment.");
    8662             :             }
    8663           0 :             if (ErrorsFoundMultiSurf) ErrorsFound = true;
    8664             : 
    8665             :         } // multi surface heat transfer algo override
    8666             : 
    8667         771 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:SurfaceList";
    8668         771 :         CountHTAlgoObjectsSurfList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8669         772 :         for (Item = 1; Item <= CountHTAlgoObjectsSurfList; ++Item) {
    8670           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8671             :                                                                      cCurrentModuleObject,
    8672             :                                                                      Item,
    8673           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8674             :                                                                      NumAlphas,
    8675           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    8676             :                                                                      NumNumbers,
    8677             :                                                                      IOStatus,
    8678           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8679           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8680           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8681           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8682           1 :             ErrorsFoundSurfList = false;
    8683             :             {
    8684           2 :                 auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
    8685             : 
    8686           1 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8687           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8688           0 :                     state.dataHeatBal->AnyCTF = true;
    8689           1 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8690           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8691           1 :                     state.dataHeatBal->AnyEMPD = true;
    8692           0 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8693           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8694           0 :                     state.dataHeatBal->AnyHAMT = true;
    8695           0 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8696           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8697           0 :                     state.dataHeatBal->AnyCondFD = true;
    8698             :                 } else {
    8699           0 :                     ShowSevereError(state,
    8700           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    8701           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    8702           0 :                     ErrorsFoundSurfList = true;
    8703             :                 }
    8704             :             }
    8705             : 
    8706           3 :             for (Item1 = 3; Item1 <= NumAlphas; ++Item1) {
    8707             : 
    8708           6 :                 Found = UtilityRoutines::FindItemInList(
    8709           6 :                     state.dataIPShortCut->cAlphaArgs(Item1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    8710             : 
    8711           2 :                 if (Found == 0) {
    8712           0 :                     ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface.");
    8713           0 :                     ShowContinueError(state, "Name of surface not found = \"" + state.dataIPShortCut->cAlphaArgs(Item1) + "\"");
    8714           0 :                     ErrorsFoundSurfList = true;
    8715             :                 }
    8716             : 
    8717           2 :                 if (!ErrorsFoundSurfList) {
    8718           2 :                     state.dataSurface->Surface(Found).HeatTransferAlgorithm = tmpAlgoInput;
    8719             :                 } else {
    8720           0 :                     ErrorsFound = true;
    8721             :                 }
    8722             :             }
    8723             :         }
    8724             : 
    8725         771 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:Construction";
    8726         771 :         CountHTAlgoObjectsSurfList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8727         772 :         for (Item = 1; Item <= CountHTAlgoObjectsSurfList; ++Item) {
    8728           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8729             :                                                                      cCurrentModuleObject,
    8730             :                                                                      Item,
    8731           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8732             :                                                                      NumAlphas,
    8733           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    8734             :                                                                      NumNumbers,
    8735             :                                                                      IOStatus,
    8736           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8737           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8738           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8739           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8740           1 :             ErrorsFoundByConstruct = false;
    8741             :             {
    8742           2 :                 auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
    8743             : 
    8744           1 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8745           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8746           0 :                     state.dataHeatBal->AnyCTF = true;
    8747           1 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8748           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8749           0 :                     state.dataHeatBal->AnyEMPD = true;
    8750           1 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8751           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8752           1 :                     state.dataHeatBal->AnyHAMT = true;
    8753           0 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8754           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8755           0 :                     state.dataHeatBal->AnyCondFD = true;
    8756             :                 } else {
    8757           0 :                     ShowSevereError(state,
    8758           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    8759           0 :                                         state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
    8760           0 :                     ErrorsFoundByConstruct = true;
    8761             :                 }
    8762             :             }
    8763             : 
    8764           3 :             Found = UtilityRoutines::FindItemInList(
    8765           3 :                 state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    8766           1 :             if (Found == 0) {
    8767           0 :                 ShowSevereError(state,
    8768           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
    8769           0 :                                     state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
    8770           0 :                 ErrorsFoundByConstruct = true;
    8771             :             }
    8772             : 
    8773           1 :             if (!ErrorsFoundByConstruct) {
    8774           7 :                 for (Item1 = 1; Item1 <= state.dataSurface->TotSurfaces; ++Item1) {
    8775           6 :                     if (state.dataSurface->Surface(Item1).Construction == Found) {
    8776           1 :                         state.dataSurface->Surface(Item1).HeatTransferAlgorithm = tmpAlgoInput;
    8777             :                     }
    8778             :                 }
    8779             :             }
    8780             :         }
    8781             : 
    8782             :         // Change algorithm for Kiva and air boundary foundation surfaces
    8783       44533 :         for (auto &surf : state.dataSurface->Surface) {
    8784       43762 :             if (surf.ExtBoundCond == KivaFoundation) {
    8785          38 :                 surf.HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::Kiva;
    8786          38 :                 state.dataHeatBal->AnyKiva = true;
    8787             :             }
    8788             :         }
    8789             : 
    8790             :         // test for missing materials for algorithms selected
    8791         771 :         NumEMPDMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:MoisturePenetrationDepth:Settings");
    8792        2313 :         NumPCMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:PhaseChange") +
    8793        1542 :                    state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:PhaseChangeHysteresis");
    8794         771 :         NumVTCMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:VariableThermalConductivity");
    8795         771 :         NumHAMTMat1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Settings");
    8796         771 :         NumHAMTMat2 =
    8797        1542 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm");
    8798         771 :         NumHAMTMat3 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Suction");
    8799         771 :         NumHAMTMat4 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Redistribution");
    8800         771 :         NumHAMTMat5 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Diffusion");
    8801         771 :         NumHAMTMat6 =
    8802        1542 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity");
    8803         771 :         SumHAMTMat = NumHAMTMat1 + NumHAMTMat2 + NumHAMTMat3 + NumHAMTMat4 + NumHAMTMat5 + NumHAMTMat6;
    8804         771 :         msgneeded = false;
    8805             : 
    8806         771 :         if (NumEMPDMat > 0 && !state.dataHeatBal->AnyEMPD) {
    8807           0 :             ShowWarningError(state,
    8808           0 :                              format("The input file includes {} MaterialProperty:MoisturePenetrationDepth:Settings objects but the moisture "
    8809             :                                     "penetration depth algorithm is not used anywhere.",
    8810           0 :                                     NumEMPDMat));
    8811           0 :             msgneeded = true;
    8812             :         }
    8813         771 :         if (NumPCMat > 0 && !state.dataHeatBal->AnyCondFD) {
    8814           0 :             ShowWarningError(state,
    8815           0 :                              format("The input file includes {} MaterialProperty:PhaseChange objects but the conduction finite difference algorithm "
    8816             :                                     "is not used anywhere.",
    8817           0 :                                     NumPCMat));
    8818           0 :             msgneeded = true;
    8819             :         }
    8820         771 :         if (NumVTCMat > 0 && !state.dataHeatBal->AnyCondFD) {
    8821           0 :             ShowWarningError(state,
    8822           0 :                              format("The input file includes {} MaterialProperty:VariableThermalConductivity objects but the conduction finite "
    8823             :                                     "difference algorithm is not used anywhere.",
    8824           0 :                                     NumVTCMat));
    8825           0 :             msgneeded = true;
    8826             :         }
    8827         771 :         if (SumHAMTMat > 0 && !state.dataHeatBal->AnyHAMT) {
    8828           0 :             ShowWarningError(state,
    8829           0 :                              format("The input file includes {} MaterialProperty:HeatAndMoistureTransfer:* objects but the combined heat and "
    8830             :                                     "moisture finite difference algorithm is not used anywhere.",
    8831           0 :                                     SumHAMTMat));
    8832           0 :             msgneeded = true;
    8833             :         }
    8834         771 :         if (msgneeded) {
    8835           0 :             ShowContinueError(state, "Previous materials will be ignored due to HeatBalanceAlgorithm choice.");
    8836             :         }
    8837         771 :         msgneeded = false;
    8838         771 :         if (NumEMPDMat == 0 && state.dataHeatBal->AnyEMPD) {
    8839           0 :             ShowWarningError(state,
    8840             :                              "The moisture penetration depth conduction transfer function algorithm is used but the input file includes no "
    8841             :                              "MaterialProperty:MoisturePenetrationDepth:Settings objects.");
    8842           0 :             msgneeded = true;
    8843             :         }
    8844         771 :         if (SumHAMTMat == 0 && state.dataHeatBal->AnyHAMT) {
    8845           0 :             ShowWarningError(state,
    8846             :                              "The combined heat and moisture finite element algorithm is used but the input file includes no "
    8847             :                              "MaterialProperty:HeatAndMoistureTransfer:* objects.");
    8848           0 :             msgneeded = true;
    8849             :         }
    8850         771 :         if (msgneeded) {
    8851           0 :             ShowContinueError(state,
    8852             :                               "Certain materials objects are necessary to achieve proper results with the heat transfer algorithm(s) selected.");
    8853             :         }
    8854             : 
    8855             :         // Write Solution Algorithm to the initialization output file for User Verification
    8856         771 :         print(state.files.eio,
    8857             :               "{}\n",
    8858             :               "! <Surface Heat Transfer Algorithm>, Value {CTF - ConductionTransferFunction | EMPD - "
    8859             :               "MoisturePenetrationDepthConductionTransferFunction | CondFD - ConductionFiniteDifference | HAMT - "
    8860             :               "CombinedHeatAndMoistureFiniteElement} - Description,Inside Surface Max Temperature Limit{C}, Surface "
    8861         771 :               "Convection Coefficient Lower Limit {W/m2-K}, Surface Convection Coefficient Upper Limit {W/m2-K}");
    8862             : 
    8863         771 :         int numberOfHeatTransferAlgosUsed = 0;
    8864             :         // Formats
    8865             :         static constexpr std::string_view Format_725("Surface Heat Transfer Algorithm, {},{:.0R},{:.2R},{:.1R}\n");
    8866             : 
    8867         771 :         if (state.dataHeatBal->AnyCTF) {
    8868         758 :             const auto AlgoName = "CTF - ConductionTransferFunction";
    8869         758 :             ++numberOfHeatTransferAlgosUsed;
    8870        2274 :             print(state.files.eio,
    8871             :                   Format_725,
    8872             :                   AlgoName,
    8873         758 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    8874         758 :                   state.dataHeatBal->LowHConvLimit,
    8875         758 :                   state.dataHeatBal->HighHConvLimit);
    8876             :         }
    8877         771 :         if (state.dataHeatBal->AnyEMPD) {
    8878           2 :             state.dataHeatBal->AllCTF = false;
    8879           2 :             const auto AlgoName = "EMPD - MoisturePenetrationDepthConductionTransferFunction";
    8880           2 :             ++numberOfHeatTransferAlgosUsed;
    8881           6 :             print(state.files.eio,
    8882             :                   Format_725,
    8883             :                   AlgoName,
    8884           2 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    8885           2 :                   state.dataHeatBal->LowHConvLimit,
    8886           2 :                   state.dataHeatBal->HighHConvLimit);
    8887           2 :             if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
    8888           0 :                 ShowSevereError(
    8889             :                     state,
    8890             :                     "MoisturePenetrationDepthConductionTransferFunction is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
    8891           0 :                 ErrorsFound = true;
    8892             :             }
    8893             :         }
    8894         771 :         if (state.dataHeatBal->AnyCondFD) {
    8895          11 :             state.dataHeatBal->AllCTF = false;
    8896          11 :             const auto AlgoName = "CondFD - ConductionFiniteDifference";
    8897          11 :             ++numberOfHeatTransferAlgosUsed;
    8898          33 :             print(state.files.eio,
    8899             :                   Format_725,
    8900             :                   AlgoName,
    8901          11 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    8902          11 :                   state.dataHeatBal->LowHConvLimit,
    8903          11 :                   state.dataHeatBal->HighHConvLimit);
    8904             :         }
    8905         771 :         if (state.dataHeatBal->AnyHAMT) {
    8906           3 :             state.dataHeatBal->AllCTF = false;
    8907           3 :             const auto AlgoName = "HAMT - CombinedHeatAndMoistureFiniteElement";
    8908           3 :             ++numberOfHeatTransferAlgosUsed;
    8909           9 :             print(state.files.eio,
    8910             :                   Format_725,
    8911             :                   AlgoName,
    8912           3 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    8913           3 :                   state.dataHeatBal->LowHConvLimit,
    8914           3 :                   state.dataHeatBal->HighHConvLimit);
    8915           3 :             if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
    8916           0 :                 ShowSevereError(state, "CombinedHeatAndMoistureFiniteElement is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
    8917           0 :                 ErrorsFound = true;
    8918             :             }
    8919             :         }
    8920         771 :         if (state.dataHeatBal->AnyKiva) {
    8921           9 :             state.dataHeatBal->AllCTF = false;
    8922           9 :             const auto AlgoName = "KivaFoundation - TwoDimensionalFiniteDifference";
    8923           9 :             ++numberOfHeatTransferAlgosUsed;
    8924          27 :             print(state.files.eio,
    8925             :                   Format_725,
    8926             :                   AlgoName,
    8927           9 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    8928           9 :                   state.dataHeatBal->LowHConvLimit,
    8929           9 :                   state.dataHeatBal->HighHConvLimit);
    8930             :         }
    8931             : 
    8932             :         // Check HeatTransferAlgorithm for interior surfaces
    8933         771 :         if (numberOfHeatTransferAlgosUsed > 1) {
    8934             :             int ExtSurfNum;
    8935         506 :             for (Item = 1; Item <= state.dataSurface->TotSurfaces; ++Item) {
    8936         496 :                 auto &surf = state.dataSurface->Surface(Item);
    8937         496 :                 if (surf.ExtBoundCond > 0) {
    8938         560 :                     if ((surf.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::Invalid) ||
    8939         280 :                         (surf.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::None))
    8940           0 :                         continue;
    8941         280 :                     ExtSurfNum = surf.ExtBoundCond;
    8942         280 :                     auto &extSurf = state.dataSurface->Surface(ExtSurfNum);
    8943         280 :                     if (surf.HeatTransferAlgorithm != extSurf.HeatTransferAlgorithm) {
    8944           0 :                         ShowWarningError(state,
    8945             :                                          "An interior surface is defined as two surfaces with reverse constructions. The HeatTransferAlgorithm in "
    8946             :                                          "both constructions should be same.");
    8947           0 :                         ShowContinueError(state,
    8948           0 :                                           format("The HeatTransferAlgorithm of Surface: {}, is {}",
    8949             :                                                  surf.Name,
    8950           0 :                                                  DataSurfaces::HeatTransAlgoStrs[static_cast<int>(surf.HeatTransferAlgorithm)]));
    8951           0 :                         ShowContinueError(state,
    8952           0 :                                           format("The HeatTransferAlgorithm of Surface: {}, is {}",
    8953             :                                                  extSurf.Name,
    8954           0 :                                                  DataSurfaces::HeatTransAlgoStrs[static_cast<int>(extSurf.HeatTransferAlgorithm)]));
    8955           0 :                         if (surf.HeatTransferAlgorithm > extSurf.HeatTransferAlgorithm) {
    8956           0 :                             ShowContinueError(state,
    8957           0 :                                               format("The HeatTransferAlgorithm of Surface: {}, is assigned to {}. Simulation continues.",
    8958             :                                                      extSurf.Name,
    8959           0 :                                                      DataSurfaces::HeatTransAlgoStrs[static_cast<int>(surf.HeatTransferAlgorithm)]));
    8960           0 :                             extSurf.HeatTransferAlgorithm = surf.HeatTransferAlgorithm;
    8961             :                         } else {
    8962           0 :                             ShowContinueError(state,
    8963           0 :                                               format("The HeatTransferAlgorithm of Surface: {}, is assigned to {}. Simulation continues.",
    8964             :                                                      surf.Name,
    8965           0 :                                                      DataSurfaces::HeatTransAlgoStrs[static_cast<int>(extSurf.HeatTransferAlgorithm)]));
    8966           0 :                             surf.HeatTransferAlgorithm = extSurf.HeatTransferAlgorithm;
    8967             :                         }
    8968             :                     }
    8969             :                 }
    8970             :             }
    8971             :         }
    8972             : 
    8973             :         // Assign model type to windows, shading surfaces, and TDDs
    8974       44533 :         for (Item = 1; Item <= state.dataSurface->TotSurfaces; ++Item) {
    8975       43762 :             if (state.dataSurface->Surface(Item).Class == SurfaceClass::Window || state.dataSurface->Surface(Item).Class == SurfaceClass::GlassDoor) {
    8976             :                 // todo, add complex fenestration switch  HeatTransferModel_ComplexFenestration
    8977        5974 :                 if (state.dataSurface->SurfWinWindowModelType(Item) == WindowModel::BSDF) {
    8978           0 :                     state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::ComplexFenestration;
    8979             :                 } else {
    8980        5974 :                     state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::Window5;
    8981             :                 }
    8982             :             }
    8983      131246 :             if (state.dataSurface->Surface(Item).Class == SurfaceClass::Detached_B ||
    8984       87344 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::Detached_F ||
    8985      171824 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::Shading || state.dataSurface->Surface(Item).Class == SurfaceClass::Overhang ||
    8986       42220 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::Fin) {
    8987        1542 :                 state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::None;
    8988             :             }
    8989       87524 :             if (state.dataSurface->Surface(Item).Class == SurfaceClass::TDD_Diffuser ||
    8990       43762 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::TDD_Dome) {
    8991           2 :                 state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::TDD;
    8992             :             }
    8993             : 
    8994       51505 :             if (state.dataSurface->Surface(Item).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF ||
    8995        7743 :                 state.dataSurface->Surface(Item).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::EMPD) {
    8996       36062 :                 state.dataConstruction->Construct(state.dataSurface->Surface(Item).Construction).IsUsedCTF = true;
    8997             :             }
    8998             :         }
    8999         771 :     }
    9000             : 
    9001       40093 :     void GetVertices(EnergyPlusData &state,
    9002             :                      int const SurfNum,             // Current surface number
    9003             :                      int const NSides,              // Number of sides to figure
    9004             :                      Array1S<Real64> const Vertices // Vertices, in specified order
    9005             :     )
    9006             :     {
    9007             : 
    9008             :         // SUBROUTINE INFORMATION:
    9009             :         //       AUTHOR         Linda Lawrie
    9010             :         //       DATE WRITTEN   May 2000
    9011             :         //       MODIFIED       na
    9012             :         //       RE-ENGINEERED  na
    9013             : 
    9014             :         // PURPOSE OF THIS SUBROUTINE:
    9015             :         // This subroutine gets the surface vertices from the arrays
    9016             :         // passed by the calling routine.  These had previously been obtained
    9017             :         // from the InputProcessor (GetObjectItem).  This routine will provide
    9018             :         // a standard place for determining various properties of the surface
    9019             :         // from the vertices.
    9020             : 
    9021             :         // METHODOLOGY EMPLOYED:
    9022             :         // na
    9023             : 
    9024             :         // REFERENCES:
    9025             :         // na
    9026             : 
    9027             :         // Using/Aliasing
    9028             :         using namespace Vectors;
    9029             : 
    9030             :         using namespace DataErrorTracking;
    9031             : 
    9032             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    9033             : 
    9034             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9035             :         static constexpr std::string_view RoutineName("GetVertices: ");
    9036             : 
    9037             :         // INTERFACE BLOCK SPECIFICATIONS
    9038             :         // na
    9039             : 
    9040             :         // DERIVED TYPE DEFINITIONS
    9041             :         // na
    9042             : 
    9043             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9044             :         int Ptr;  // Pointer into Vertice array
    9045             :         int n;    // Loop counter
    9046             :         int NSrc; // Used for CW -> CCW transformation
    9047             :         int NTar; // Used for CW -> CCW transformation
    9048             :         Real64 SurfWorldAz;
    9049             :         Real64 SurfTilt;
    9050             :         Real64 Perimeter; // Perimeter length of the surface
    9051             :         Real64 Xb;        // Intermediate calculation
    9052             :         Real64 Yb;        // Intermediate calculation
    9053             :         int ZoneNum;
    9054             :         int ThisCorner;
    9055       80186 :         std::string TiltString;
    9056             :         Real64 ThisWidth;
    9057             :         Real64 ThisHeight;
    9058             :         Real64 DistanceCheck;
    9059             :         // unused    REAL(r64) :: ccwtest
    9060             :         // unused    LOGICAL   :: SurfaceCCW
    9061             :         Real64 dotp;
    9062             : 
    9063             :         // Object Data
    9064       80186 :         Vector const TestVector(0.0, 0.0, 1.0);
    9065       80186 :         Vector temp;
    9066             : 
    9067       40093 :         if (NSides > state.dataSurface->MaxVerticesPerSurface) state.dataSurface->MaxVerticesPerSurface = NSides;
    9068       40093 :         Ptr = 1;
    9069      201160 :         for (n = 1; n <= NSides; ++n) {
    9070      161067 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x = Vertices(Ptr);
    9071      161067 :             ++Ptr;
    9072      161067 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y = Vertices(Ptr);
    9073      161067 :             ++Ptr;
    9074      161067 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z = Vertices(Ptr);
    9075      161067 :             ++Ptr;
    9076             :         }
    9077             : 
    9078             :         // Address changing vertices if they were put in in CW order rather than CCW
    9079       40093 :         if (!state.dataSurface->CCW) {
    9080             :             // If even number of sides, this will transfer appropriately
    9081             :             // If odd number, will leave the "odd" one, which is what you want.
    9082         195 :             NSrc = NSides;
    9083         195 :             NTar = 2;
    9084         390 :             for (n = 1; n <= (NSides - 1) / 2; ++n) {
    9085         195 :                 temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc);
    9086         195 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar);
    9087         195 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar) = temp;
    9088         195 :                 --NSrc;
    9089         195 :                 ++NTar;
    9090             :             }
    9091             :         }
    9092             :         // Now address which "Corner" has been put in first.  Note: the azimuth and tilt and area
    9093             :         // calculations do not care which corner is put in first.
    9094             :         // 2/2011 - don't think the shading calculations have a corner preference.  Will keep this for
    9095             :         // consistency (for now)
    9096       40093 :         ThisCorner = state.dataSurface->Corner;
    9097       46247 :         while (ThisCorner != UpperLeftCorner) {
    9098        3077 :             if (NSides < 4) {
    9099           8 :                 if (ThisCorner == UpperRightCorner) {
    9100           0 :                     ThisCorner = UpperLeftCorner;
    9101           0 :                     break;
    9102             :                 }
    9103             :             }
    9104        3077 :             NTar = ThisCorner;
    9105        3077 :             NSrc = ThisCorner + 1;
    9106        3077 :             if (NSrc > NSides) NSrc = 1;
    9107       12584 :             for (n = 1; n <= NSides - 1; ++n) {
    9108        9507 :                 temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar);
    9109        9507 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc);
    9110        9507 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc) = temp;
    9111        9507 :                 ++NTar;
    9112        9507 :                 ++NSrc;
    9113        9507 :                 if (NTar > NSides) NTar = 1;
    9114        9507 :                 if (NSrc > NSides) NSrc = 1;
    9115             :             }
    9116        3077 :             ++ThisCorner;
    9117        3077 :             if (ThisCorner > NSides) ThisCorner = 1;
    9118             :         } // Corners
    9119       40093 :         if (!state.dataSurface->WorldCoordSystem) {
    9120             :             // Input in "relative" coordinates, use Building and Zone North Axes and Origins
    9121             :             //                                  to translate each point (including rotation for Appendix G)
    9122       31668 :             ZoneNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
    9123       31668 :             if (ZoneNum > 0) {
    9124      158707 :                 for (n = 1; n <= NSides; ++n) {
    9125      381201 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x * state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) -
    9126      127067 :                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y * state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) +
    9127      127067 :                          state.dataHeatBal->Zone(ZoneNum).OriginX;
    9128      381201 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x * state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) +
    9129      127067 :                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y * state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) +
    9130      127067 :                          state.dataHeatBal->Zone(ZoneNum).OriginY;
    9131      127067 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9132      127067 :                         Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    9133      127067 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9134      127067 :                         Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    9135      127067 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z += state.dataHeatBal->Zone(ZoneNum).OriginZ;
    9136             :                 }
    9137          28 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    9138          62 :                 for (n = 1; n <= NSides; ++n) {
    9139          48 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
    9140          48 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
    9141          48 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9142          48 :                         Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    9143          48 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9144          48 :                         Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    9145             :                 }
    9146             :             }
    9147             :         } else {
    9148             :             // if world coordinate only need to rotate for Appendix G
    9149        8425 :             ZoneNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
    9150        8425 :             if (ZoneNum > 0) {
    9151       42225 :                 for (n = 1; n <= NSides; ++n) {
    9152       33822 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
    9153       33822 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
    9154       33822 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9155       33822 :                         Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
    9156       33822 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9157       33822 :                         Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
    9158             :                 }
    9159          22 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    9160           0 :                 for (n = 1; n <= NSides; ++n) {
    9161           0 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
    9162           0 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
    9163           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9164           0 :                         Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
    9165           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9166           0 :                         Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
    9167             :                 }
    9168             :             }
    9169             :         }
    9170             : 
    9171       40093 :         if (NSides > 2) {
    9172       40093 :             auto &surface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    9173       40093 :             auto &vertices = surface.Vertex;
    9174       40093 :             auto &nSides = surface.Sides;
    9175             : 
    9176       40093 :             bool poppedVertex = true;
    9177      120279 :             while (poppedVertex) {
    9178       40093 :                 poppedVertex = false;
    9179       40093 :                 Perimeter = 0.0;
    9180             : 
    9181      201160 :                 for (auto it = vertices.begin(); it != vertices.end(); ++it) {
    9182      161067 :                     auto itnext = std::next(it);
    9183      161067 :                     if (itnext == std::end(vertices)) {
    9184       40093 :                         itnext = std::begin(vertices);
    9185             :                     }
    9186             : 
    9187             :                     // TODO: use isAlmostEqual3Pt for consistency? (which uses 0.0127 m / 1/2inch instead of 0.01 m)
    9188      161067 :                     DistanceCheck = distance(*it, *itnext);
    9189      161067 :                     if (DistanceCheck < 0.01) {
    9190           0 :                         int curVertexIndex = std::distance(vertices.begin(), it) + 1;
    9191           0 :                         int nextVertexIndex = std::distance(vertices.begin(), itnext) + 1;
    9192           0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    9193           0 :                             ShowWarningError(state,
    9194           0 :                                              format("{}Distance between two vertices < .01, possibly coincident. for Surface={}, in Zone={}",
    9195             :                                                     RoutineName,
    9196           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    9197           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
    9198           0 :                             ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", curVertexIndex, it->x, it->y, it->z));
    9199           0 :                             ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", nextVertexIndex, itnext->x, itnext->y, it->z));
    9200             :                         }
    9201           0 :                         ++state.dataErrTracking->TotalCoincidentVertices;
    9202           0 :                         if (nSides > 3) {
    9203           0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    9204           0 :                                 ShowContinueError(state, format("Dropping Vertex [{}].", nextVertexIndex));
    9205             :                             }
    9206           0 :                             --nSides;
    9207           0 :                             vertices.erase(itnext);
    9208           0 :                             poppedVertex = true;
    9209           0 :                             break;
    9210             :                         } else {
    9211           0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    9212           0 :                                 ShowContinueError(state,
    9213           0 :                                                   format("Cannot Drop Vertex [{}]; Number of Surface Sides at minimum. This surface is now a "
    9214             :                                                          "degenerate surface.",
    9215           0 :                                                          curVertexIndex));
    9216             :                             }
    9217           0 :                             ++state.dataErrTracking->TotalDegenerateSurfaces;
    9218             :                             // mark degenerate surface?
    9219             :                         }
    9220             :                     } else {
    9221      161067 :                         Perimeter += DistanceCheck;
    9222             :                     }
    9223             :                 }
    9224             :             }
    9225             : 
    9226       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
    9227             : 
    9228       80186 :             CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9229       40093 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9230       40093 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9231       80186 :             CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9232       40093 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9233       40093 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    9234             :             // For surfaces with subsurfaces, the following two areas are turned into net areas later by
    9235             :             // subtracting subsurface areas
    9236       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    9237       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    9238       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    9239      240558 :             DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9240       40093 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9241             :                                     SurfWorldAz,
    9242             :                                     SurfTilt,
    9243       40093 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    9244       40093 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    9245       40093 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    9246       40093 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
    9247       40093 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9248       40093 :             dotp = dot(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector, TestVector);
    9249       40093 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && dotp < -0.000001) {
    9250           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9251           0 :                 ShowWarningError(state,
    9252           0 :                                  std::string{RoutineName} + "Roof/Ceiling is upside down! Tilt angle=[" + TiltString +
    9253           0 :                                      "], should be near 0, Surface=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
    9254           0 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
    9255           0 :                 ShowContinueError(state, "Automatic fix is attempted.");
    9256           0 :                 ReverseAndRecalculate(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, SurfWorldAz, SurfTilt);
    9257       40093 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && SurfTilt > 80.0) {
    9258           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9259           0 :                 ShowWarningError(state,
    9260           0 :                                  std::string{RoutineName} + "Roof/Ceiling is not oriented correctly! Tilt angle=[" + TiltString +
    9261           0 :                                      "], should be near 0, Surface=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
    9262           0 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
    9263             :             }
    9264       40093 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && dotp > 0.000001) {
    9265           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9266           0 :                 ShowWarningError(state,
    9267           0 :                                  std::string{RoutineName} + "Floor is upside down! Tilt angle=[" + TiltString + "], should be near 180, Surface=\"" +
    9268           0 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
    9269           0 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
    9270           0 :                 ShowContinueError(state, "Automatic fix is attempted.");
    9271           0 :                 ReverseAndRecalculate(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, SurfWorldAz, SurfTilt);
    9272       40093 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && SurfTilt < 158.2) { // slope/grade = 40%!
    9273           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9274           0 :                 ShowWarningError(state,
    9275           0 :                                  std::string{RoutineName} + "Floor is not oriented correctly! Tilt angle=[" + TiltString +
    9276           0 :                                      "], should be near 180, Surface=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
    9277           0 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
    9278             :             }
    9279       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfWorldAz;
    9280       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    9281       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    9282       40093 :                 ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    9283             : 
    9284             :             // Sine and cosine of azimuth and tilt
    9285       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
    9286       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
    9287       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
    9288       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
    9289       40093 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround == DataGlobalConstants::AutoCalculate) {
    9290       18565 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround =
    9291       18565 :                     0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9292             :             }
    9293             :             // Outward normal unit vector (pointing away from room)
    9294       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    9295      160372 :             for (n = 1; n <= 3; ++n) {
    9296      120279 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    9297       15097 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    9298      120279 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    9299       17121 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    9300      120279 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    9301       72277 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    9302             :             }
    9303             : 
    9304      114870 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    9305       74273 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    9306       34180 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    9307        6369 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area *= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    9308             :             // Can perform tests on this surface here
    9309       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9310             :             // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    9311             :             // surfaces
    9312       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    9313       40093 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9314             : 
    9315             :             // Call to transform vertices
    9316             : 
    9317       40093 :             TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    9318             : 
    9319             :         } else {
    9320           0 :             ShowFatalError(
    9321           0 :                 state, std::string{RoutineName} + "Called with less than 2 sides, Surface=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    9322             :         }
    9323             : 
    9324             :         // Preliminary Height/Width
    9325       40093 :         temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
    9326       40093 :         ThisWidth = VecLength(temp);
    9327       40093 :         temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
    9328       40093 :         ThisHeight = VecLength(temp);
    9329       40093 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = ThisHeight;
    9330       40093 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = ThisWidth;
    9331       40093 :     }
    9332             : 
    9333           0 :     void ReverseAndRecalculate(EnergyPlusData &state,
    9334             :                                int const SurfNum,   // Surface number for the surface
    9335             :                                int const NSides,    // number of sides to surface
    9336             :                                Real64 &SurfAzimuth, // Surface Facing angle (will be 0 for roofs/floors)
    9337             :                                Real64 &SurfTilt     // Surface tilt (
    9338             :     )
    9339             :     {
    9340             : 
    9341             :         // SUBROUTINE INFORMATION:
    9342             :         //       AUTHOR         Linda Lawrie
    9343             :         //       DATE WRITTEN   February 2011
    9344             :         //       MODIFIED       na
    9345             :         //       RE-ENGINEERED  na
    9346             : 
    9347             :         // PURPOSE OF THIS SUBROUTINE:
    9348             :         // This routine reverses the vertices for a surface (needed when roof/floor is upside down)
    9349             :         // and recalculates the azimuth, etc for the surface.
    9350             : 
    9351             :         // METHODOLOGY EMPLOYED:
    9352             :         // na
    9353             : 
    9354             :         // REFERENCES:
    9355             :         // na
    9356             : 
    9357             :         // Using/Aliasing
    9358             :         using namespace Vectors;
    9359             : 
    9360             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    9361             : 
    9362             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9363             :         static constexpr std::string_view RoutineName("ReverseAndRecalculate: ");
    9364             : 
    9365             :         // INTERFACE BLOCK SPECIFICATIONS:
    9366             :         // na
    9367             : 
    9368             :         // DERIVED TYPE DEFINITIONS:
    9369             :         // na
    9370             : 
    9371             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9372             :         int n;      // Loop Control
    9373             :         int RevPtr; // pointer for reversing vertices
    9374           0 :         std::string TiltString;
    9375             : 
    9376             :         // Object Data
    9377           0 :         Array1D<Vector> Vertices(NSides); // Vertices, in specified order
    9378             : 
    9379           0 :         for (n = 1; n <= NSides; ++n) {
    9380           0 :             Vertices(n) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n);
    9381             :         }
    9382           0 :         RevPtr = NSides;
    9383           0 :         for (n = 1; n <= NSides; ++n) {
    9384           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n) = Vertices(RevPtr);
    9385           0 :             --RevPtr;
    9386             :         }
    9387             : 
    9388           0 :         print(state.files.debug, "Reversing Surface Name={}\n", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    9389           0 :         for (n = 1; n <= NSides; ++n) {
    9390           0 :             print(state.files.debug,
    9391             :                   "side={:5} abs coord vertex= {:18.13F} {:18.13F} {:18.13F}\n",
    9392             :                   n,
    9393           0 :                   state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x,
    9394           0 :                   state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y,
    9395           0 :                   state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z);
    9396             :         }
    9397             : 
    9398           0 :         CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9399           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9400           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9401           0 :         DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9402           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9403             :                                 SurfAzimuth,
    9404             :                                 SurfTilt,
    9405           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    9406           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    9407           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    9408           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
    9409           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9410           0 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && SurfTilt > 80.0) {
    9411           0 :             TiltString = format("{:.1R}", SurfTilt);
    9412           0 :             ShowWarningError(state,
    9413           0 :                              std::string{RoutineName} + "Roof/Ceiling is still upside down! Tilt angle=[" + TiltString +
    9414             :                                  "], should be near 0, please fix manually.");
    9415             :         }
    9416           0 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && SurfTilt < 158.2) { // 40% grade!
    9417           0 :             ShowWarningError(state,
    9418           0 :                              std::string{RoutineName} + "Floor is still upside down! Tilt angle=[" + TiltString +
    9419             :                                  "], should be near 180, please fix manually.");
    9420             :         }
    9421           0 :     }
    9422             : 
    9423         771 :     void MakeMirrorSurface(EnergyPlusData &state, int &SurfNum) // In=>Surface to Mirror, Out=>new Surface index
    9424             :     {
    9425             : 
    9426             :         // SUBROUTINE INFORMATION:
    9427             :         //       AUTHOR         Linda Lawrie
    9428             :         //       DATE WRITTEN   June 2002
    9429             :         //       MODIFIED       na
    9430             :         //       RE-ENGINEERED  na
    9431             : 
    9432             :         // PURPOSE OF THIS SUBROUTINE:
    9433             :         // This subroutine creates a "mirror" surface using the indicated surface.
    9434             :         // This is the simple approach for bi-directional shading devices.  If, perchance,
    9435             :         // the user has already taken care of this (e.g. fins in middle of wall), there will
    9436             :         // be extra shading devices shown.
    9437             : 
    9438             :         // METHODOLOGY EMPLOYED:
    9439             :         // Reverse the vertices in the original surface.  Add "bi" to name.
    9440             : 
    9441             :         using namespace Vectors;
    9442             : 
    9443             :         int Vert;
    9444             :         int NVert;
    9445             :         Real64 SurfWorldAz;
    9446             :         Real64 SurfTilt;
    9447             :         int n;
    9448             :         //  TYPE(Vector) :: temp1
    9449             : 
    9450         771 :         NVert = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
    9451         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Vertex.allocate(NVert);
    9452             :         // doesn't work when Vertex are pointers  SurfaceTmp(SurfNum+1)=SurfaceTmp(SurfNum)
    9453         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    9454         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Construction = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    9455         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ConstructionStoredInputValue =
    9456         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue;
    9457         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Class = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class;
    9458         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).GrossArea = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    9459         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    9460         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
    9461         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Height = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height;
    9462         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Reveal = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Reveal;
    9463         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Shape = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Shape;
    9464         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Sides = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
    9465         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Tilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
    9466         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ConvOrientation =
    9467         771 :             ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    9468         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Width = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width;
    9469         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).HeatTransSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf;
    9470         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
    9471         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).BaseSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf;
    9472         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName;
    9473         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Zone = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
    9474         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName;
    9475         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond;
    9476         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar;
    9477         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind;
    9478         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorGround = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround;
    9479         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorSky = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    9480         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorGroundIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR;
    9481         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR;
    9482         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).SchedShadowSurfIndex = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex;
    9483         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).SchedMinValue = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue;
    9484         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).IsTransparent = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent;
    9485         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).activeWindowShadingControl =
    9486         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl;
    9487        1542 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).windowShadingControlList =
    9488        1542 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
    9489         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).HasShadeControl = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl;
    9490         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).activeShadedConstruction =
    9491         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
    9492         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).FrameDivider = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider;
    9493         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Multiplier = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    9494         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc;
    9495         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Perimeter = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter;
    9496             : 
    9497        3833 :         for (Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) {
    9498        3062 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Vertex(Vert) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NVert);
    9499        3062 :             --NVert;
    9500             :         }
    9501         771 :         ++SurfNum;
    9502         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = "Mir-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum - 1).Name;
    9503             : 
    9504             :         // TH 3/26/2010
    9505         771 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).MirroredSurf = true;
    9506             : 
    9507         771 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides > 2) {
    9508        1542 :             CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9509         771 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9510         771 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    9511         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    9512         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    9513         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    9514        1542 :             CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9515         771 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9516         771 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9517        4626 :             DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9518         771 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9519             :                                     SurfWorldAz,
    9520             :                                     SurfTilt,
    9521         771 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    9522         771 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    9523         771 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    9524         771 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
    9525         771 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9526         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfWorldAz;
    9527         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    9528         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
    9529         771 :                 ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    9530             : 
    9531             :             // Sine and cosine of azimuth and tilt
    9532         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
    9533         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
    9534         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
    9535         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
    9536             :             // Outward normal unit vector (pointing away from room)
    9537         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    9538        3084 :             for (n = 1; n <= 3; ++n) {
    9539        2313 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    9540         705 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    9541        2313 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    9542          54 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    9543        2313 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    9544        1530 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    9545             :             }
    9546             : 
    9547             :             // Can perform tests on this surface here
    9548         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9549             :             // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    9550             :             // surfaces
    9551         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    9552         771 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9553             :         }
    9554         771 :     }
    9555             : 
    9556         771 :     void GetWindowShadingControlData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    9557             :     {
    9558             : 
    9559             :         // SUBROUTINE INFORMATION:
    9560             :         //       AUTHOR         Fred Winkelmann
    9561             :         //       DATE WRITTEN   November 1998
    9562             :         //       MODIFIED       Aug 2001 (FW): add handling of new ShadingControlIsScheduled
    9563             :         //                      and GlareControlIsActive fields
    9564             :         //                      Nov 2001 (FW): add ShadingDevice as alternative to ShadedConstruction
    9565             :         //                      Dec 2001 (FW): add slat angle controls for blinds
    9566             :         //                      Aug 2002 (FW): add Setpoint2; check that specified control type is legal
    9567             :         //                      Feb 2003 (FW): add error if Material Name of Shading Device is used with
    9568             :         //                        Shading Type = BetweenGlassShade or BetweenGlassBlind
    9569             :         //                      Dec 2003 (FW): improve BetweenGlassBlind error messages
    9570             :         //                      Feb 2009 (BG): improve error checking for OnIfScheduleAllows
    9571             :         //       RE-ENGINEERED  na
    9572             : 
    9573             :         // PURPOSE OF THIS SUBROUTINE:
    9574             :         // Reads in the window shading control information
    9575             :         // from the input data file, interprets it and puts it in the derived type
    9576             : 
    9577             :         // Using/Aliasing
    9578             :         using ScheduleManager::GetScheduleIndex;
    9579             : 
    9580             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9581             : 
    9582         771 :         int constexpr NumValidShadingTypes(9);
    9583             :         static Array1D_string const cValidShadingTypes(NumValidShadingTypes,
    9584             :                                                        {
    9585             :                                                            "SHADEOFF",          // 1
    9586             :                                                            "INTERIORSHADE",     // 2
    9587             :                                                            "SWITCHABLEGLAZING", // 3
    9588             :                                                            "EXTERIORSHADE",     // 4
    9589             :                                                            "EXTERIORSCREEN",    // 5
    9590             :                                                            "INTERIORBLIND",     // 6
    9591             :                                                            "EXTERIORBLIND",     // 7
    9592             :                                                            "BETWEENGLASSSHADE", // 8
    9593             :                                                            "BETWEENGLASSBLIND"  // 9
    9594         771 :                                                        });
    9595             : 
    9596         771 :         constexpr std::array<std::string_view, static_cast<int>(WindowShadingControlType::Num)> WindowShadingControlTypeNamesUC{
    9597             :             "ALWAYSON",
    9598             :             "ALWAYSOFF",
    9599             :             "ONIFSCHEDULEALLOWS",
    9600             :             "ONIFHIGHSOLARONWINDOW",
    9601             :             "ONIFHIGHHORIZONTALSOLAR",
    9602             :             "ONIFHIGHOUTDOORAIRTEMPERATURE",
    9603             :             "ONIFHIGHZONEAIRTEMPERATURE",
    9604             :             "ONIFHIGHZONECOOLING",
    9605             :             "ONIFHIGHGLARE",
    9606             :             "MEETDAYLIGHTILLUMINANCESETPOINT",
    9607             :             "ONNIGHTIFLOWOUTDOORTEMPANDOFFDAY",
    9608             :             "ONNIGHTIFLOWINSIDETEMPANDOFFDAY",
    9609             :             "ONNIGHTIFHEATINGANDOFFDAY",
    9610             :             "ONNIGHTIFLOWOUTDOORTEMPANDONDAYIFCOOLING",
    9611             :             "ONNIGHTIFHEATINGANDONDAYIFCOOLING",
    9612             :             "OFFNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW",
    9613             :             "ONNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW",
    9614             :             "ONIFHIGHOUTDOORAIRTEMPANDHIGHSOLARONWINDOW",
    9615             :             "ONIFHIGHOUTDOORAIRTEMPANDHIGHHORIZONTALSOLAR",
    9616             :             "ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW",
    9617             :             "ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR",
    9618             :             "ONIFHIGHSOLARORHIGHLUMINANCETILLMIDNIGHT",
    9619             :             "ONIFHIGHSOLARORHIGHLUMINANCETILLSUNSET",
    9620             :             "ONIFHIGHSOLARORHIGHLUMINANCETILLNEXTMORNING"};
    9621             : 
    9622         771 :         constexpr std::array<std::string_view, static_cast<int>(SlatAngleControl::Num)> SlatAngleNamesUC{
    9623             :             "FIXEDSLATANGLE", "SCHEDULEDSLATANGLE", "BLOCKBEAMSOLAR"};
    9624             : 
    9625         771 :         constexpr std::array<std::string_view, static_cast<int>(MultiSurfaceControl::Num)> MultiSurfaceControlNamesUC = {"SEQUENTIAL", "GROUP"};
    9626             : 
    9627             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9628             :         int IOStat;          // IO Status when calling get input subroutine
    9629             :         int ControlNumAlpha; // Number of control alpha names being passed
    9630             :         int ControlNumProp;  // Number of control properties being passed
    9631             :         int ControlNum;      // DO loop counter/index for window shading control number
    9632             :         int IShadedConst;    // Construction number of shaded construction
    9633             :         int IShadingDevice;  // Material number of shading device
    9634             :         int NLayers;         // Layers in shaded construction
    9635             :         bool ErrorInName;
    9636             :         bool IsBlank;
    9637             :         int Loop;
    9638             :         bool BGShadeBlindError; // True if problem with construction that is supposed to have between-glass
    9639             :         // shade or blind
    9640             :         int Found;
    9641             : 
    9642         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    9643             :         // Get the total number of window shading control blocks
    9644         771 :         cCurrentModuleObject = "WindowShadingControl";
    9645         771 :         state.dataSurface->TotWinShadingControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    9646         771 :         if (state.dataSurface->TotWinShadingControl == 0) return;
    9647             : 
    9648          42 :         state.dataSurface->WindowShadingControl.allocate(state.dataSurface->TotWinShadingControl);
    9649             : 
    9650          42 :         ControlNum = 0;
    9651         114 :         for (Loop = 1; Loop <= state.dataSurface->TotWinShadingControl; ++Loop) {
    9652             : 
    9653         504 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    9654             :                                                                      cCurrentModuleObject,
    9655             :                                                                      Loop,
    9656          72 :                                                                      state.dataIPShortCut->cAlphaArgs,
    9657             :                                                                      ControlNumAlpha,
    9658          72 :                                                                      state.dataIPShortCut->rNumericArgs,
    9659             :                                                                      ControlNumProp,
    9660             :                                                                      IOStat,
    9661          72 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    9662          72 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    9663          72 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    9664          72 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    9665             : 
    9666          72 :             ErrorInName = false;
    9667          72 :             IsBlank = false;
    9668         144 :             UtilityRoutines::VerifyName(state,
    9669          72 :                                         state.dataIPShortCut->cAlphaArgs(1),
    9670          72 :                                         state.dataSurface->WindowShadingControl,
    9671             :                                         ControlNum,
    9672             :                                         ErrorInName,
    9673             :                                         IsBlank,
    9674         144 :                                         cCurrentModuleObject + " Name");
    9675          72 :             if (ErrorInName) {
    9676           0 :                 ErrorsFound = true;
    9677           0 :                 continue;
    9678             :             }
    9679             : 
    9680          72 :             ++ControlNum;
    9681             : 
    9682          72 :             auto &windowShadingControl = state.dataSurface->WindowShadingControl(ControlNum);
    9683             : 
    9684          72 :             windowShadingControl.Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Control Name in the Derived Type
    9685             : 
    9686          72 :             windowShadingControl.ZoneIndex = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
    9687          72 :             if (windowShadingControl.ZoneIndex == 0) {
    9688           0 :                 ShowSevereError(state,
    9689           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
    9690           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\" not found.");
    9691           0 :                 ErrorsFound = true;
    9692             :             }
    9693             : 
    9694          72 :             windowShadingControl.SequenceNumber = int(state.dataIPShortCut->rNumericArgs(1));
    9695             :             // WindowShadingControl().getInputShadedConstruction is only used during GetInput process and is ultimately stored in
    9696             :             // Surface().shadedConstructionList
    9697         216 :             windowShadingControl.getInputShadedConstruction = UtilityRoutines::FindItemInList(
    9698         216 :                 state.dataIPShortCut->cAlphaArgs(4), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    9699          72 :             windowShadingControl.ShadingDevice =
    9700          72 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(9), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
    9701          72 :             windowShadingControl.Schedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
    9702          72 :             windowShadingControl.SetPoint = state.dataIPShortCut->rNumericArgs(2);
    9703          72 :             windowShadingControl.SetPoint2 = state.dataIPShortCut->rNumericArgs(3);
    9704          72 :             windowShadingControl.ShadingControlIsScheduled = getYesNoValue(state.dataIPShortCut->cAlphaArgs(7)) == BooleanSwitch::Yes;
    9705          72 :             windowShadingControl.GlareControlIsActive = getYesNoValue(state.dataIPShortCut->cAlphaArgs(8)) == BooleanSwitch::Yes;
    9706          72 :             windowShadingControl.SlatAngleSchedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
    9707             : 
    9708             :             // store the string for now and associate it after daylighting control objects are read
    9709          72 :             windowShadingControl.DaylightingControlName = state.dataIPShortCut->cAlphaArgs(12);
    9710             : 
    9711          72 :             windowShadingControl.multiSurfaceControl = static_cast<MultiSurfaceControl>(
    9712         144 :                 getEnumerationValue(MultiSurfaceControlNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(13))));
    9713             : 
    9714          72 :             if (windowShadingControl.multiSurfaceControl == MultiSurfaceControl::Invalid) {
    9715           0 :                 windowShadingControl.multiSurfaceControl = MultiSurfaceControl::Sequential;
    9716           0 :                 ShowWarningError(state,
    9717           0 :                                  format("{}=\"{}\" should be either SEQUENTIAL or GROUP {}=\"{}\", defaulting to \"SEQUENTIAL\"",
    9718             :                                         cCurrentModuleObject,
    9719             :                                         windowShadingControl.Name,
    9720           0 :                                         state.dataIPShortCut->cAlphaFieldNames(13),
    9721           0 :                                         state.dataIPShortCut->cAlphaArgs(13)));
    9722             :             }
    9723             : 
    9724          72 :             if (ControlNumAlpha >= 14) {
    9725          72 :                 windowShadingControl.FenestrationCount = ControlNumAlpha - 13;
    9726          72 :                 windowShadingControl.FenestrationName.allocate(windowShadingControl.FenestrationCount);
    9727          72 :                 windowShadingControl.FenestrationIndex.allocate(windowShadingControl.FenestrationCount);
    9728         219 :                 for (int i = 1; i <= windowShadingControl.FenestrationCount; i++) {
    9729         147 :                     windowShadingControl.FenestrationName(i) = state.dataIPShortCut->cAlphaArgs(i + 13);
    9730             :                 }
    9731             :             } else {
    9732           0 :                 ShowSevereError(state,
    9733           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    9734             :                                     "\" invalid. Must reference at least one Fenestration Surface object name.");
    9735             :             }
    9736             : 
    9737          72 :             windowShadingControl.shadingControlType = static_cast<WindowShadingControlType>(
    9738         144 :                 getEnumerationValue(WindowShadingControlTypeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(5))));
    9739             : 
    9740          72 :             if (windowShadingControl.ShadingDevice > 0) {
    9741          13 :                 if (state.dataMaterial->Material(windowShadingControl.ShadingDevice).Group == DataHeatBalance::MaterialGroup::Screen &&
    9742           0 :                     !(windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOn ||
    9743           0 :                       windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOff ||
    9744           0 :                       windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled)) {
    9745           0 :                     ErrorsFound = true;
    9746           0 :                     ShowSevereError(state,
    9747           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " +
    9748           0 :                                         state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
    9749             :                                         "\" for exterior screens.");
    9750           0 :                     ShowContinueError(state,
    9751             :                                       "Valid shading control types for exterior window screens are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.");
    9752             :                 }
    9753             :             } else {
    9754          59 :                 if (windowShadingControl.getInputShadedConstruction > 0) {
    9755          59 :                     state.dataConstruction->Construct(windowShadingControl.getInputShadedConstruction).IsUsed = true;
    9756         118 :                     if (state.dataMaterial->Material(state.dataConstruction->Construct(windowShadingControl.getInputShadedConstruction).LayerPoint(1))
    9757          61 :                                 .Group == DataHeatBalance::MaterialGroup::Screen &&
    9758           6 :                         !(windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOn ||
    9759           2 :                           windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOff ||
    9760           2 :                           windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled)) {
    9761           0 :                         ErrorsFound = true;
    9762           0 :                         ShowSevereError(state,
    9763           0 :                                         cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " +
    9764           0 :                                             state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
    9765             :                                             "\" for exterior screens.");
    9766           0 :                         ShowContinueError(state,
    9767             :                                           "Valid shading control types for exterior window screens are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.");
    9768             :                     }
    9769           0 :                 } else if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    9770           0 :                     ShowSevereError(state,
    9771           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\", " + state.dataIPShortCut->cAlphaFieldNames(4) +
    9772             :                                         " is blank.");
    9773           0 :                     ShowContinueError(state, "A valid construction is required.");
    9774           0 :                     ErrorsFound = true;
    9775             :                 } else {
    9776           0 :                     ShowSevereError(state,
    9777           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\", " + state.dataIPShortCut->cAlphaFieldNames(4) +
    9778             :                                         " is invalid.");
    9779           0 :                     ShowContinueError(state,
    9780           0 :                                       "Construction=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\" was used. A valid construction is required.");
    9781           0 :                     ErrorsFound = true;
    9782             :                 }
    9783             :             }
    9784             : 
    9785             :             // Warning if setpoint is unintentionally zero
    9786         104 :             if (windowShadingControl.SetPoint == 0 && windowShadingControl.shadingControlType != WindowShadingControlType::AlwaysOn &&
    9787          64 :                 windowShadingControl.shadingControlType != WindowShadingControlType::AlwaysOff &&
    9788          54 :                 windowShadingControl.shadingControlType != WindowShadingControlType::OnIfScheduled &&
    9789          22 :                 windowShadingControl.shadingControlType != WindowShadingControlType::HiGlare) {
    9790           0 :                 ShowWarningError(state, cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\", The first SetPoint is zero.");
    9791           0 :                 ShowContinueError(state, "..You may have forgotten to specify that setpoint.");
    9792             :             }
    9793             : 
    9794             :             // Error checks
    9795          72 :             if (state.dataIPShortCut->cAlphaArgs(7) != "YES" && state.dataIPShortCut->cAlphaArgs(7) != "NO") { // Shading Control is Schedule field
    9796           0 :                 ErrorsFound = true;
    9797           0 :                 ShowSevereError(state,
    9798           0 :                                 cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(7) +
    9799           0 :                                     "=\"" + state.dataIPShortCut->cAlphaArgs(7) + "\".");
    9800             :             }
    9801          72 :             if (state.dataIPShortCut->cAlphaArgs(8) != "YES" && state.dataIPShortCut->cAlphaArgs(8) != "NO") { // Glare Control is Active field
    9802           0 :                 ErrorsFound = true;
    9803           0 :                 ShowSevereError(state,
    9804           0 :                                 cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(8) +
    9805           0 :                                     "=\"" + state.dataIPShortCut->cAlphaArgs(8) + "\".");
    9806             :             }
    9807             : 
    9808          84 :             if ((windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled) &&
    9809          12 :                 (!windowShadingControl.ShadingControlIsScheduled)) { // CR 7709 BG
    9810           0 :                 ErrorsFound = true;
    9811           0 :                 ShowSevereError(state,
    9812           0 :                                 cCurrentModuleObject + " = \"" + windowShadingControl.Name + "\" invalid, " +
    9813           0 :                                     state.dataIPShortCut->cAlphaFieldNames(7) + " must be set to \"Yes\" for " +
    9814           0 :                                     state.dataIPShortCut->cAlphaFieldNames(5) + " = OnIfScheduleAllows");
    9815             :             }
    9816          72 :             windowShadingControl.slatAngleControl = static_cast<SlatAngleControl>(
    9817         144 :                 getEnumerationValue(SlatAngleNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(10))));
    9818             : 
    9819             :             // For upward compatibility change old "noninsulating" and "insulating" shade types to
    9820             :             // INTERIORSHADE or EXTERIORSHADE
    9821         144 :             if (state.dataIPShortCut->cAlphaArgs(3) == "INTERIORNONINSULATINGSHADE" ||
    9822          72 :                 state.dataIPShortCut->cAlphaArgs(3) == "INTERIORINSULATINGSHADE") {
    9823           0 :                 ShowWarningError(state,
    9824           0 :                                  cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" is using obsolete " +
    9825           0 :                                      state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9826             :                                      "\", changing to \"InteriorShade\"");
    9827           0 :                 windowShadingControl.ShadingType = WinShadingType::IntShade;
    9828           0 :                 state.dataIPShortCut->cAlphaArgs(3) = "INTERIORSHADE";
    9829             :             }
    9830         144 :             if (state.dataIPShortCut->cAlphaArgs(3) == "EXTERIORNONINSULATINGSHADE" ||
    9831          72 :                 state.dataIPShortCut->cAlphaArgs(3) == "EXTERIORINSULATINGSHADE") {
    9832           0 :                 ShowWarningError(state,
    9833           0 :                                  cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" is using obsolete " +
    9834           0 :                                      state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9835             :                                      "\", changing to \"ExteriorShade\"");
    9836           0 :                 windowShadingControl.ShadingType = WinShadingType::ExtShade;
    9837           0 :                 state.dataIPShortCut->cAlphaArgs(3) = "EXTERIORSHADE";
    9838             :             }
    9839             : 
    9840          73 :             if (windowShadingControl.shadingControlType == WindowShadingControlType::MeetDaylIlumSetp &&
    9841           1 :                 state.dataIPShortCut->cAlphaArgs(3) != "SWITCHABLEGLAZING") {
    9842           0 :                 ErrorsFound = true;
    9843           0 :                 ShowSevereError(state,
    9844           0 :                                 cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(3) +
    9845           0 :                                     "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
    9846           0 :                 ShowContinueError(state,
    9847           0 :                                   "..." + state.dataIPShortCut->cAlphaFieldNames(3) +
    9848           0 :                                       " must be SwitchableGlazing for this control, but entered type=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9849             :                                       "\".");
    9850             :             }
    9851             : 
    9852             :             // Check for illegal shading type name
    9853          72 :             Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), cValidShadingTypes, NumValidShadingTypes);
    9854          72 :             if (Found <= 1) {
    9855           0 :                 ErrorsFound = true;
    9856           0 :                 ShowSevereError(state,
    9857           0 :                                 cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(3) +
    9858           0 :                                     "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
    9859             :             } else {
    9860          72 :                 windowShadingControl.ShadingType = WinShadingType(Found);
    9861             :             }
    9862             : 
    9863          72 :             WinShadingType ShTyp = windowShadingControl.ShadingType;
    9864          72 :             IShadedConst = windowShadingControl.getInputShadedConstruction;
    9865          72 :             IShadingDevice = windowShadingControl.ShadingDevice;
    9866             : 
    9867          72 :             if (IShadedConst == 0 && IShadingDevice == 0) {
    9868           0 :                 ShowSevereError(
    9869           0 :                     state, cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has no matching shaded construction or shading device.");
    9870           0 :                 ErrorsFound = true;
    9871          72 :             } else if (IShadedConst == 0 && IShadingDevice > 0) {
    9872          13 :                 if (ShTyp == WinShadingType::SwitchableGlazing) {
    9873           0 :                     ShowSevereError(state,
    9874           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
    9875             :                                         "= SwitchableGlazing but no matching shaded construction");
    9876           0 :                     ErrorsFound = true;
    9877             :                 }
    9878          26 :                 if ((ShTyp == WinShadingType::IntShade || ShTyp == WinShadingType::ExtShade) &&
    9879          13 :                     state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Shade) {
    9880           0 :                     ShowSevereError(state,
    9881           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
    9882             :                                         "= InteriorShade or ExteriorShade but matching shading device is not a window shade");
    9883           0 :                     ShowContinueError(state,
    9884           0 :                                       state.dataIPShortCut->cAlphaFieldNames(8) + " in error=\"" + state.dataMaterial->Material(IShadingDevice).Name +
    9885             :                                           "\".");
    9886           0 :                     ErrorsFound = true;
    9887             :                 }
    9888          13 :                 if ((ShTyp == WinShadingType::ExtScreen) &&
    9889           0 :                     state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Screen) {
    9890           0 :                     ShowSevereError(state,
    9891           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
    9892             :                                         "= ExteriorScreen but matching shading device is not a window screen");
    9893           0 :                     ShowContinueError(state,
    9894           0 :                                       state.dataIPShortCut->cAlphaFieldNames(8) + " in error=\"" + state.dataMaterial->Material(IShadingDevice).Name +
    9895             :                                           "\".");
    9896           0 :                     ErrorsFound = true;
    9897             :                 }
    9898          13 :                 if ((ShTyp == WinShadingType::IntBlind || ShTyp == WinShadingType::ExtBlind) &&
    9899           0 :                     state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::WindowBlind) {
    9900           0 :                     ShowSevereError(state,
    9901           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
    9902             :                                         "= InteriorBlind or ExteriorBlind but matching shading device is not a window blind");
    9903           0 :                     ShowContinueError(state,
    9904           0 :                                       state.dataIPShortCut->cAlphaFieldNames(8) + " in error=\"" + state.dataMaterial->Material(IShadingDevice).Name +
    9905             :                                           "\".");
    9906           0 :                     ErrorsFound = true;
    9907             :                 }
    9908          26 :                 if (ShTyp == WinShadingType::BGShade || ShTyp == WinShadingType::BGBlind) {
    9909           0 :                     ShowSevereError(state,
    9910           0 :                                     cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
    9911             :                                         "= BetweenGlassShade or BetweenGlassBlind and");
    9912           0 :                     ShowContinueError(
    9913           0 :                         state, state.dataIPShortCut->cAlphaFieldNames(8) + " is specified. This is illegal. Specify shaded construction instead.");
    9914           0 :                     ErrorsFound = true;
    9915             :                 }
    9916          59 :             } else if (IShadedConst > 0 && IShadingDevice > 0) {
    9917           0 :                 IShadingDevice = 0;
    9918           0 :                 ShowWarningError(state,
    9919           0 :                                  cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" Both " + state.dataIPShortCut->cAlphaFieldNames(4) +
    9920           0 :                                      " and " + state.dataIPShortCut->cAlphaFieldNames(9) + " are specified.");
    9921           0 :                 ShowContinueError(state,
    9922           0 :                                   "The " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataConstruction->Construct(IShadedConst).Name +
    9923             :                                       "\" will be used.");
    9924             :             }
    9925             : 
    9926             :             // If type = interior or exterior shade or blind require that the shaded construction
    9927             :             // have a shade layer in the correct position
    9928          72 :             if (IShadedConst != 0) {
    9929             : 
    9930          59 :                 NLayers = state.dataConstruction->Construct(IShadedConst).TotLayers;
    9931          59 :                 BGShadeBlindError = false;
    9932          59 :                 IShadingDevice = 0;
    9933          59 :                 if (state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers) != 0) {
    9934          59 :                     if (windowShadingControl.ShadingType == WinShadingType::IntShade) {
    9935          10 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers);
    9936          10 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers)).Group !=
    9937             :                             DataHeatBalance::MaterialGroup::Shade) {
    9938           0 :                             ErrorsFound = true;
    9939           0 :                             ShowSevereError(state,
    9940           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
    9941           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
    9942           0 :                             ShowContinueError(state,
    9943           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9944             :                                                   "\" should have a shade layer on the inside of the window.");
    9945             :                         }
    9946          49 :                     } else if (windowShadingControl.ShadingType == WinShadingType::ExtShade) {
    9947           5 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
    9948           5 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1)).Group !=
    9949             :                             DataHeatBalance::MaterialGroup::Shade) {
    9950           0 :                             ErrorsFound = true;
    9951           0 :                             ShowSevereError(state,
    9952           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
    9953           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(43) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
    9954           0 :                             ShowContinueError(state,
    9955           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9956             :                                                   "\" should have a shade layer on the outside of the window.");
    9957             :                         }
    9958          44 :                     } else if (windowShadingControl.ShadingType == WinShadingType::ExtScreen) {
    9959           2 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
    9960           2 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1)).Group !=
    9961             :                             DataHeatBalance::MaterialGroup::Screen) {
    9962           0 :                             ErrorsFound = true;
    9963           0 :                             ShowSevereError(state,
    9964           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
    9965           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
    9966           0 :                             ShowContinueError(state,
    9967           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9968             :                                                   "\" should have a screen layer on the outside of the window.");
    9969             :                         }
    9970          42 :                     } else if (windowShadingControl.ShadingType == WinShadingType::IntBlind) {
    9971          12 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers);
    9972          12 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers)).Group !=
    9973             :                             DataHeatBalance::MaterialGroup::WindowBlind) {
    9974           0 :                             ErrorsFound = true;
    9975           0 :                             ShowSevereError(state,
    9976           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
    9977           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
    9978           0 :                             ShowContinueError(state,
    9979           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9980             :                                                   "\" should have a blind layer on the inside of the window.");
    9981             :                         }
    9982          30 :                     } else if (windowShadingControl.ShadingType == WinShadingType::ExtBlind) {
    9983           2 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
    9984           2 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1)).Group !=
    9985             :                             DataHeatBalance::MaterialGroup::WindowBlind) {
    9986           0 :                             ErrorsFound = true;
    9987           0 :                             ShowSevereError(state,
    9988           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
    9989           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
    9990           0 :                             ShowContinueError(state,
    9991           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
    9992             :                                                   "\" should have a blind layer on the outside of the window.");
    9993             :                         }
    9994          28 :                     } else if (windowShadingControl.ShadingType == WinShadingType::BGShade) {
    9995           2 :                         if (NLayers != 5 && NLayers != 7) BGShadeBlindError = true;
    9996           2 :                         if (NLayers == 5) {
    9997           1 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(3)).Group !=
    9998             :                                 DataHeatBalance::MaterialGroup::Shade)
    9999           0 :                                 BGShadeBlindError = true;
   10000             :                         }
   10001           2 :                         if (NLayers == 7) {
   10002           1 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(5)).Group !=
   10003             :                                 DataHeatBalance::MaterialGroup::Shade)
   10004           0 :                                 BGShadeBlindError = true;
   10005             :                         }
   10006           2 :                         if (BGShadeBlindError) {
   10007           0 :                             ErrorsFound = true;
   10008           0 :                             ShowSevereError(state,
   10009           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
   10010           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10011           0 :                             ShowContinueError(state,
   10012           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(32) +
   10013             :                                                   "\" should have two or three glass layers and a");
   10014           0 :                             ShowContinueError(state, "between-glass shade layer with a gas layer on each side.");
   10015             :                         }
   10016          26 :                     } else if (windowShadingControl.ShadingType == WinShadingType::BGBlind) {
   10017           3 :                         if (NLayers != 5 && NLayers != 7) BGShadeBlindError = true;
   10018           3 :                         if (NLayers == 5) {
   10019           2 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(3)).Group !=
   10020             :                                 DataHeatBalance::MaterialGroup::WindowBlind)
   10021           0 :                                 BGShadeBlindError = true;
   10022             :                         }
   10023           3 :                         if (NLayers == 7) {
   10024           1 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(5)).Group !=
   10025             :                                 DataHeatBalance::MaterialGroup::WindowBlind)
   10026           0 :                                 BGShadeBlindError = true;
   10027             :                         }
   10028           3 :                         if (BGShadeBlindError) {
   10029           0 :                             ErrorsFound = true;
   10030           0 :                             ShowSevereError(state,
   10031           0 :                                             cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
   10032           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10033           0 :                             ShowContinueError(state,
   10034           0 :                                               "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
   10035             :                                                   "\" should have two or three glass layers and a");
   10036           0 :                             ShowContinueError(state, "between-glass blind layer with a gas layer on each side.");
   10037             :                         }
   10038             :                     }
   10039             :                 }
   10040          59 :                 if (IShadingDevice > 0) {
   10041          46 :                     if ((ShTyp == WinShadingType::IntShade || ShTyp == WinShadingType::ExtShade) &&
   10042          15 :                         state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Shade) {
   10043           0 :                         ShowSevereError(state,
   10044           0 :                                         cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " +
   10045           0 :                                             state.dataIPShortCut->cAlphaFieldNames(3) +
   10046             :                                             "= InteriorShade or ExteriorShade but matching shading device is not a window shade");
   10047           0 :                         ShowContinueError(state, "Shading Device in error=\"" + state.dataMaterial->Material(IShadingDevice).Name + "\".");
   10048           0 :                         ErrorsFound = true;
   10049             :                     }
   10050          33 :                     if ((ShTyp == WinShadingType::ExtScreen) &&
   10051           2 :                         state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Screen) {
   10052           0 :                         ShowSevereError(state,
   10053           0 :                                         cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " +
   10054           0 :                                             state.dataIPShortCut->cAlphaFieldNames(3) +
   10055             :                                             "= ExteriorScreen but matching shading device is not an exterior window screen.");
   10056           0 :                         ShowContinueError(state, "Shading Device in error=\"" + state.dataMaterial->Material(IShadingDevice).Name + "\".");
   10057           0 :                         ErrorsFound = true;
   10058             :                     }
   10059          45 :                     if ((ShTyp == WinShadingType::IntBlind || ShTyp == WinShadingType::ExtBlind) &&
   10060          14 :                         state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::WindowBlind) {
   10061           0 :                         ShowSevereError(state,
   10062           0 :                                         cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " +
   10063           0 :                                             state.dataIPShortCut->cAlphaFieldNames(3) +
   10064             :                                             "= InteriorBlind or ExteriorBlind but matching shading device is not a window blind.");
   10065           0 :                         ShowContinueError(state, "Shading Device in error=\"" + state.dataMaterial->Material(IShadingDevice).Name + "\".");
   10066           0 :                         ErrorsFound = true;
   10067             :                     }
   10068             :                 }
   10069             :             }
   10070             :         } // End of loop over window shading controls
   10071             :     }
   10072             : 
   10073        5982 :     void InitialAssociateWindowShadingControlFenestration(EnergyPlusData &state, bool &ErrorsFound, int &SurfNum)
   10074             :     {
   10075             :         // J.Glazer 2018 - operates on SurfaceTmp array before final indices are known for windows and sets the activeWindowShadingControl
   10076        7663 :         for (int iShadeCtrl = 1; iShadeCtrl <= state.dataSurface->TotWinShadingControl; ++iShadeCtrl) {
   10077        1681 :             int curShadedConstruction = state.dataSurface->WindowShadingControl(iShadeCtrl).getInputShadedConstruction;
   10078        6591 :             for (int jFeneRef = 1; jFeneRef <= state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationCount; ++jFeneRef) {
   10079        4910 :                 if (UtilityRoutines::SameString(state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationName(jFeneRef),
   10080        4910 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) {
   10081         147 :                     state.dataGlobal->AndShadingControlInModel = true;
   10082         147 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = true;
   10083         147 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.push_back(iShadeCtrl);
   10084         147 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = iShadeCtrl;
   10085         147 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.push_back(curShadedConstruction);
   10086         147 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = curShadedConstruction;
   10087             : 
   10088             :                     // check to make the window refenced is an exterior window
   10089         147 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment) {
   10090           0 :                         ErrorsFound = true;
   10091           0 :                         ShowSevereError(state,
   10092           0 :                                         "InitialAssociateWindowShadingControlFenestration: \"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
   10093           0 :                                             "\", invalid " + " because it is not an exterior window.");
   10094           0 :                         ShowContinueError(
   10095           0 :                             state, ".. It appears on WindowShadingControl object: \"" + state.dataSurface->WindowShadingControl(iShadeCtrl).Name);
   10096             :                     }
   10097             :                     // check to make sure the window is not using equivalent layer window construction
   10098         147 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
   10099           0 :                         ErrorsFound = true;
   10100           0 :                         ShowSevereError(state,
   10101           0 :                                         "InitialAssociateWindowShadingControlFenestration: =\"" +
   10102           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " + "\".");
   10103           0 :                         ShowContinueError(state, ".. equivalent layer window model does not use shading control object.");
   10104           0 :                         ShowContinueError(state, ".. Shading control is set to none or zero, and simulation continues.");
   10105           0 :                         ShowContinueError(
   10106           0 :                             state, ".. It appears on WindowShadingControl object: \"" + state.dataSurface->WindowShadingControl(iShadeCtrl).Name);
   10107           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
   10108             :                     }
   10109             :                 }
   10110             :             }
   10111             :         }
   10112        5982 :     }
   10113             : 
   10114       43762 :     void FinalAssociateWindowShadingControlFenestration(EnergyPlusData &state, bool &ErrorsFound)
   10115             :     {
   10116             :         // J.Glazer 2018 - operates on Surface array after final indices are known for windows and checks to make sure it is correct
   10117       51402 :         for (int iShadeCtrl = 1; iShadeCtrl <= state.dataSurface->TotWinShadingControl; ++iShadeCtrl) {
   10118       25527 :             for (int jFeneRef = 1; jFeneRef <= state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationCount; ++jFeneRef) {
   10119             :                 int fenestrationIndex =
   10120       35774 :                     UtilityRoutines::FindItemInList(state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationName(jFeneRef),
   10121       17887 :                                                     state.dataSurface->Surface,
   10122       35774 :                                                     state.dataSurface->TotSurfaces);
   10123       53661 :                 if (std::find(state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.begin(),
   10124       35774 :                               state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.end(),
   10125       53661 :                               iShadeCtrl) != state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.end()) {
   10126       17887 :                     state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationIndex(jFeneRef) = fenestrationIndex;
   10127             :                 } else {
   10128             :                     // this error condition should not occur since the rearrangement of Surface() from SurfureTmp() is reliable.
   10129           0 :                     ErrorsFound = true;
   10130           0 :                     ShowSevereError(state,
   10131           0 :                                     "FinalAssociateWindowShadingControlFenestration: Fenestration surface named \"" +
   10132           0 :                                         state.dataSurface->Surface(fenestrationIndex).Name +
   10133             :                                         "\" has WindowShadingContol index that does not match the initial index assigned.");
   10134           0 :                     ShowContinueError(state,
   10135           0 :                                       "This occurs while WindowShadingControl object: \"" + state.dataSurface->WindowShadingControl(iShadeCtrl).Name +
   10136             :                                           "\" is being evaluated. ");
   10137             :                 }
   10138             :             }
   10139             :         }
   10140       43762 :     }
   10141             : 
   10142       43762 :     void CheckWindowShadingControlSimilarForWindow(EnergyPlusData &state, bool &ErrorsFound)
   10143             :     {
   10144             :         // For each window check if all window shading controls on list are the same except for name, schedule name, construction, and
   10145             :         // material
   10146    11618580 :         for (auto &theSurf : state.dataSurface->Surface) {
   10147    11574818 :             if (theSurf.HasShadeControl) {
   10148       17747 :                 if (theSurf.windowShadingControlList.size() > 1) {
   10149         140 :                     int firstWindowShadingControl = theSurf.windowShadingControlList.front();
   10150         280 :                     for (auto wsc = std::next(theSurf.windowShadingControlList.begin()); wsc != theSurf.windowShadingControlList.end(); ++wsc) {
   10151         140 :                         if (!isWindowShadingControlSimilar(state, firstWindowShadingControl, *wsc)) {
   10152           0 :                             ErrorsFound = true;
   10153           0 :                             ShowSevereError(state,
   10154           0 :                                             "CheckWindowShadingControlSimilarForWindow: Fenestration surface named \"" + theSurf.Name +
   10155             :                                                 "\" has multiple WindowShadingContols that are not similar.");
   10156           0 :                             ShowContinueError(state,
   10157           0 :                                               "for: \"" + state.dataSurface->WindowShadingControl(firstWindowShadingControl).Name +
   10158           0 :                                                   " and: " + state.dataSurface->WindowShadingControl(*wsc).Name);
   10159             :                         }
   10160             :                     }
   10161             :                 }
   10162             :             }
   10163             :         }
   10164       43762 :     }
   10165             : 
   10166         140 :     bool isWindowShadingControlSimilar(EnergyPlusData &state, int a, int b)
   10167             :     {
   10168             :         // Compares two window shading controls are the same except for the name, schedule name, construction, and material
   10169         140 :         auto &WindowShadingControlA(state.dataSurface->WindowShadingControl(a));
   10170         140 :         auto &WindowShadingControlB(state.dataSurface->WindowShadingControl(b));
   10171         280 :         return (WindowShadingControlA.ZoneIndex == WindowShadingControlB.ZoneIndex &&
   10172         280 :                 WindowShadingControlA.ShadingType == WindowShadingControlB.ShadingType &&
   10173         280 :                 WindowShadingControlA.shadingControlType == WindowShadingControlB.shadingControlType &&
   10174         280 :                 WindowShadingControlA.SetPoint == WindowShadingControlB.SetPoint &&
   10175         280 :                 WindowShadingControlA.ShadingControlIsScheduled == WindowShadingControlB.ShadingControlIsScheduled &&
   10176         280 :                 WindowShadingControlA.GlareControlIsActive == WindowShadingControlB.GlareControlIsActive &&
   10177         280 :                 WindowShadingControlA.slatAngleControl == WindowShadingControlB.slatAngleControl &&
   10178         280 :                 WindowShadingControlA.SetPoint2 == WindowShadingControlB.SetPoint2 &&
   10179         280 :                 WindowShadingControlA.DaylightingControlName == WindowShadingControlB.DaylightingControlName &&
   10180         420 :                 WindowShadingControlA.DaylightControlIndex == WindowShadingControlB.DaylightControlIndex &&
   10181         280 :                 WindowShadingControlA.multiSurfaceControl == WindowShadingControlB.multiSurfaceControl);
   10182             :     }
   10183             : 
   10184         771 :     void GetStormWindowData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
   10185             :     {
   10186             : 
   10187             :         // SUBROUTINE INFORMATION:
   10188             :         //       AUTHOR         Fred Winkelmann
   10189             :         //       DATE WRITTEN   December 2003
   10190             :         //       MODIFIED       na
   10191             : 
   10192             :         //       RE-ENGINEERED  na
   10193             : 
   10194             :         // PURPOSE OF THIS SUBROUTINE:
   10195             :         // Reads in the storm window data from the input file,
   10196             :         // interprets it and puts it in the derived type
   10197             : 
   10198             :         // Using/Aliasing
   10199             : 
   10200             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   10201             : 
   10202             :         int IOStat;           // IO Status when calling get input subroutine
   10203             :         int StormWinNumAlpha; // Number of alpha names being passed
   10204             :         int StormWinNumProp;  // Number of properties being passed
   10205             :         int StormWinNum;      // Index for storm window number
   10206             :         int loop;             // Do loop counter
   10207             :         int SurfNum;          // Surface number
   10208             :         int MatNum;           // Material number
   10209             : 
   10210         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   10211             : 
   10212             :         // Get the total number of storm window input objects
   10213         771 :         cCurrentModuleObject = "WindowProperty:StormWindow";
   10214         771 :         state.dataSurface->TotStormWin = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   10215         771 :         if (state.dataSurface->TotStormWin == 0) return;
   10216             : 
   10217           1 :         state.dataSurface->StormWindow.allocate(state.dataSurface->TotStormWin);
   10218             : 
   10219           1 :         StormWinNum = 0;
   10220           1 :         for (loop = 1; loop <= state.dataSurface->TotStormWin; ++loop) {
   10221             : 
   10222           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   10223             :                                                                      cCurrentModuleObject,
   10224             :                                                                      loop,
   10225           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
   10226             :                                                                      StormWinNumAlpha,
   10227           1 :                                                                      state.dataIPShortCut->rNumericArgs,
   10228             :                                                                      StormWinNumProp,
   10229             :                                                                      IOStat,
   10230           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   10231           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   10232           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   10233           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   10234           1 :             ++StormWinNum;
   10235           1 :             state.dataSurface->StormWindow(StormWinNum).BaseWindowNum =
   10236           1 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
   10237           1 :             state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum =
   10238           1 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
   10239           1 :             state.dataSurface->StormWindow(StormWinNum).StormWinDistance = state.dataIPShortCut->rNumericArgs(1);
   10240           1 :             state.dataSurface->StormWindow(StormWinNum).MonthOn = state.dataIPShortCut->rNumericArgs(2);
   10241           1 :             state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn = state.dataIPShortCut->rNumericArgs(3);
   10242           1 :             state.dataSurface->StormWindow(StormWinNum).DateOn =
   10243           1 :                 General::OrdinalDay(state.dataSurface->StormWindow(StormWinNum).MonthOn, state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn, 1);
   10244           1 :             state.dataSurface->StormWindow(StormWinNum).MonthOff = state.dataIPShortCut->rNumericArgs(4);
   10245           1 :             state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff = state.dataIPShortCut->rNumericArgs(5);
   10246           2 :             state.dataSurface->StormWindow(StormWinNum).DateOff = General::OrdinalDay(
   10247           2 :                 state.dataSurface->StormWindow(StormWinNum).MonthOff, state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff, 1);
   10248             : 
   10249           1 :             if (state.dataSurface->StormWindow(StormWinNum).DateOn == state.dataSurface->StormWindow(StormWinNum).DateOff) {
   10250           0 :                 ShowSevereError(state,
   10251           0 :                                 format("{}: Date On = Date Off -- not allowed, occurred in WindowProperty:StormWindow Input #{}",
   10252             :                                        cCurrentModuleObject,
   10253           0 :                                        StormWinNum));
   10254           0 :                 ErrorsFound = true;
   10255             :             }
   10256             : 
   10257             :             enum Month
   10258             :             {
   10259             :                 January = 1,
   10260             :                 February,
   10261             :                 March,
   10262             :                 April,
   10263             :                 May,
   10264             :                 June,
   10265             :                 July,
   10266             :                 August,
   10267             :                 September,
   10268             :                 October,
   10269             :                 November,
   10270             :                 December
   10271             :             };
   10272           1 :             constexpr std::array<int, 13> oneBasedDaysInMonth = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   10273             : 
   10274           1 :             int const monthOn = state.dataSurface->StormWindow(StormWinNum).MonthOn;
   10275           1 :             if (monthOn >= January && monthOn <= December) {
   10276           2 :                 if (state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn >
   10277           1 :                     oneBasedDaysInMonth[state.dataSurface->StormWindow(StormWinNum).MonthOn]) {
   10278           0 :                     ShowSevereError(state,
   10279           0 :                                     format("{}: Date On (Day of Month) [{}], invalid for WindowProperty:StormWindow Input #{}",
   10280             :                                            cCurrentModuleObject,
   10281           0 :                                            state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn,
   10282           0 :                                            StormWinNum));
   10283           0 :                     ErrorsFound = true;
   10284             :                 }
   10285           2 :                 break;
   10286             :             } else {
   10287           0 :                 ShowSevereError(state,
   10288           0 :                                 format("{}: Date On Month [{}], invalid for WindowProperty:StormWindow Input #{}",
   10289             :                                        cCurrentModuleObject,
   10290           0 :                                        state.dataSurface->StormWindow(StormWinNum).MonthOn,
   10291           0 :                                        StormWinNum));
   10292           0 :                 ErrorsFound = true;
   10293             :             }
   10294             : 
   10295           0 :             int const monthOff = state.dataSurface->StormWindow(StormWinNum).MonthOff;
   10296           0 :             if (monthOff >= January && monthOff <= December) {
   10297           0 :                 if (state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff >
   10298           0 :                     oneBasedDaysInMonth[state.dataSurface->StormWindow(StormWinNum).MonthOff]) {
   10299           0 :                     ShowSevereError(state,
   10300           0 :                                     format("{}: Date Off (Day of Month) [{}], invalid for WindowProperty:StormWindow Input #{}",
   10301             :                                            cCurrentModuleObject,
   10302           0 :                                            state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff,
   10303           0 :                                            StormWinNum));
   10304           0 :                     ErrorsFound = true;
   10305             :                 }
   10306           0 :                 break;
   10307             :             } else {
   10308           0 :                 ShowSevereError(state,
   10309           0 :                                 format("{}: Date Off Month [{}], invalid for WindowProperty:StormWindow Input #{}",
   10310             :                                        cCurrentModuleObject,
   10311           0 :                                        state.dataSurface->StormWindow(StormWinNum).MonthOff,
   10312           0 :                                        StormWinNum));
   10313           0 :                 ErrorsFound = true;
   10314             :             }
   10315             :         }
   10316             : 
   10317             :         // Error checks
   10318             : 
   10319           2 :         for (StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
   10320             :             // Require BaseWindowNum be that of an exterior window
   10321           1 :             SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum;
   10322           1 :             if (SurfNum == 0) {
   10323           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid.");
   10324           0 :                 ErrorsFound = true;
   10325             :             } else {
   10326           1 :                 if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Window || state.dataSurface->Surface(SurfNum).ExtBoundCond != 0) {
   10327           0 :                     ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
   10328           0 :                     ShowSevereError(state, "cannot be used with surface=" + state.dataSurface->Surface(SurfNum).Name);
   10329           0 :                     ShowContinueError(state, "because that surface is not an exterior window.");
   10330           0 :                     ErrorsFound = true;
   10331             :                 }
   10332             :             }
   10333             : 
   10334             :             // Require that storm window material be glass
   10335           1 :             MatNum = state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum;
   10336           1 :             if (SurfNum > 0) {
   10337           1 :                 if (MatNum == 0) {
   10338           0 :                     ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
   10339           0 :                     ShowContinueError(state,
   10340           0 :                                       state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
   10341             :                                           "\" not found as storm window layer.");
   10342           0 :                     ErrorsFound = true;
   10343             :                 } else {
   10344           1 :                     if (state.dataMaterial->Material(MatNum).Group != DataHeatBalance::MaterialGroup::WindowGlass) {
   10345           0 :                         ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
   10346           0 :                         ShowContinueError(state,
   10347           0 :                                           state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
   10348             :                                               "must be a WindowMaterial:Glazing or WindowMaterial:Glazing:RefractionExtinctionMethod");
   10349           0 :                         ErrorsFound = true;
   10350             :                     }
   10351             :                 }
   10352             :             }
   10353             : 
   10354             :             // Error if base window has airflow control
   10355           1 :             if (SurfNum > 0) {
   10356           1 :                 if (state.dataSurface->SurfWinAirflowControlType(SurfNum) != DataSurfaces::WindowAirFlowControlType::Invalid) {
   10357           0 :                     ShowSevereError(
   10358             :                         state,
   10359           0 :                         format("{}=\"{} cannot be used because it is an airflow window (i.e., has WindowProperty:AirflowControl specified)",
   10360             :                                cCurrentModuleObject,
   10361           0 :                                state.dataIPShortCut->cAlphaArgs(1)));
   10362           0 :                     ErrorsFound = true;
   10363             :                 }
   10364             :             }
   10365             : 
   10366             :             // Check for reversal of on and off times
   10367           1 :             if (SurfNum > 0) {
   10368           3 :                 if ((state.dataEnvrn->Latitude > 0.0 &&
   10369           2 :                      (state.dataSurface->StormWindow(StormWinNum).MonthOn < state.dataSurface->StormWindow(StormWinNum).MonthOff)) ||
   10370           1 :                     (state.dataEnvrn->Latitude <= 0.0 &&
   10371           0 :                      (state.dataSurface->StormWindow(StormWinNum).MonthOn > state.dataSurface->StormWindow(StormWinNum).MonthOff))) {
   10372           0 :                     ShowWarningError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" check times that storm window");
   10373           0 :                     ShowContinueError(state,
   10374           0 :                                       format("is put on (month={}, day={}) and taken off (month={}, day={});",
   10375           0 :                                              state.dataSurface->StormWindow(StormWinNum).MonthOn,
   10376           0 :                                              state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn,
   10377           0 :                                              state.dataSurface->StormWindow(StormWinNum).MonthOff,
   10378           0 :                                              state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff));
   10379           0 :                     ShowContinueError(state, format("these times may be reversed for your building latitude={:.2R} deg.", state.dataEnvrn->Latitude));
   10380             :                 }
   10381             :             }
   10382             :         }
   10383             :     }
   10384             : 
   10385         771 :     void GetWindowGapAirflowControlData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
   10386             :     {
   10387             : 
   10388             :         // SUBROUTINE INFORMATION:
   10389             :         //       AUTHOR         Fred Winkelmann
   10390             :         //       DATE WRITTEN   Feb 2003
   10391             :         //       MODIFIED       June 2003, FCW: add destination = return air;
   10392             :         //                        more error messages
   10393             :         //       RE-ENGINEERED  na
   10394             : 
   10395             :         // PURPOSE OF THIS SUBROUTINE:
   10396             :         // Reads in the window airflow control information from the input data file,
   10397             :         // interprets it and puts it in the SurfaceWindow derived type
   10398             : 
   10399             :         // Using/Aliasing
   10400             :         using ScheduleManager::GetScheduleIndex;
   10401             : 
   10402             :         static constexpr std::string_view RoutineName("GetWindowGapAirflowControlData");
   10403             :         int IOStat;               // IO Status when calling get input subroutine
   10404             :         int ControlNumAlpha;      // Number of control alpha names being passed
   10405             :         int ControlNumProp;       // Number of control properties being passed
   10406             :         int TotWinAirflowControl; // Total window airflow control statements
   10407             :         bool WrongSurfaceType;    // True if associated surface is not 2- or 3-pane exterior window
   10408             :         int Loop;
   10409             :         int SurfNum;      // Surface number
   10410         771 :         int ConstrNum(0); // Construction number
   10411             :         int ConstrNumSh;  // Shaded Construction number
   10412             :         int MatGapFlow;   // Material number of gas in airflow gap of window's construction
   10413             :         int MatGapFlow1;  // Material number of gas on either side of a between-glass shade/blind
   10414             :         int MatGapFlow2;
   10415             : 
   10416         771 :         constexpr std::array<std::string_view, static_cast<int>(WindowAirFlowSource::Num)> WindowAirFlowSourceNamesUC{"INDOORAIR", "OUTDOORAIR"};
   10417         771 :         constexpr std::array<std::string_view, static_cast<int>(WindowAirFlowDestination::Num)> WindowAirFlowDestinationNamesUC{
   10418             :             "INDOORAIR", "OUTDOORAIR", "RETURNAIR"};
   10419             : 
   10420             :         // of the shaded construction of airflow window
   10421         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   10422             :         // Get the total number of window airflow control statements
   10423         771 :         cCurrentModuleObject = "WindowProperty:AirflowControl";
   10424         771 :         TotWinAirflowControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   10425         771 :         if (TotWinAirflowControl == 0) return;
   10426             : 
   10427          10 :         for (Loop = 1; Loop <= TotWinAirflowControl; ++Loop) { // Loop through all surfaces in the input...
   10428             : 
   10429          56 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   10430             :                                                                      cCurrentModuleObject,
   10431             :                                                                      Loop,
   10432           8 :                                                                      state.dataIPShortCut->cAlphaArgs,
   10433             :                                                                      ControlNumAlpha,
   10434           8 :                                                                      state.dataIPShortCut->rNumericArgs,
   10435             :                                                                      ControlNumProp,
   10436             :                                                                      IOStat,
   10437           8 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   10438           8 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   10439           8 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   10440           8 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   10441             : 
   10442           8 :             SurfNum =
   10443           8 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
   10444           8 :             if (SurfNum == 0) {
   10445           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" not found.");
   10446           0 :                 ErrorsFound = true;
   10447             :             }
   10448             :             // Check that associated surface is a 2- or 3-pane exterior window
   10449           8 :             WrongSurfaceType = false;
   10450           8 :             if (SurfNum != 0) {
   10451           8 :                 if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Window) WrongSurfaceType = true;
   10452           8 :                 if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
   10453           8 :                     ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
   10454          12 :                     if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers != 2 &&
   10455           4 :                         state.dataConstruction->Construct(ConstrNum).TotGlassLayers != 3)
   10456           0 :                         WrongSurfaceType = true;
   10457           8 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCond != ExternalEnvironment) WrongSurfaceType = true;
   10458             :                 }
   10459           8 :                 if (WrongSurfaceType) {
   10460           0 :                     ShowSevereError(state,
   10461           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
   10462             :                                         "\" is not an exterior window with 2 or 3 glass layers.");
   10463           0 :                     ErrorsFound = true;
   10464             :                 }
   10465             :             }
   10466             : 
   10467             :             // Error if illegal airflow source
   10468           8 :             if (state.dataIPShortCut->cAlphaArgs(2) != "INDOORAIR" && state.dataIPShortCut->cAlphaArgs(2) != "OUTDOORAIR") {
   10469           0 :                 ErrorsFound = true;
   10470           0 :                 ShowSevereError(state,
   10471           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
   10472           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\"");
   10473             :             }
   10474             : 
   10475             :             // Error if illegal airflow destination
   10476           8 :             if (state.dataIPShortCut->cAlphaArgs(3) != "INDOORAIR" && state.dataIPShortCut->cAlphaArgs(3) != "OUTDOORAIR" &&
   10477           0 :                 state.dataIPShortCut->cAlphaArgs(3) != "RETURNAIR") {
   10478           0 :                 ErrorsFound = true;
   10479           0 :                 ShowSevereError(state,
   10480           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
   10481           0 :                                     state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\"");
   10482             :             }
   10483             : 
   10484             :             // Error if source = OutsideAir and destination = ReturnAir
   10485           8 :             if (state.dataIPShortCut->cAlphaArgs(2) == "OUTDOORAIR" && state.dataIPShortCut->cAlphaArgs(3) == "RETURNAIR") {
   10486           0 :                 ErrorsFound = true;
   10487           0 :                 ShowSevereError(state,
   10488           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
   10489           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\"");
   10490           0 :                 ShowContinueError(state, "..when " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\"");
   10491             :             }
   10492             : 
   10493             :             // Error if illegal airflow control type
   10494           8 :             if (state.dataIPShortCut->cAlphaArgs(4) != "ALWAYSONATMAXIMUMFLOW" && state.dataIPShortCut->cAlphaArgs(4) != "ALWAYSOFF" &&
   10495           0 :                 state.dataIPShortCut->cAlphaArgs(4) != "SCHEDULEDONLY") {
   10496           0 :                 ErrorsFound = true;
   10497           0 :                 ShowSevereError(state,
   10498           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
   10499           0 :                                     state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10500             :             }
   10501             : 
   10502             :             // Error if illegal value for Airflow Has Multiplier Schedule
   10503           8 :             if (state.dataIPShortCut->cAlphaArgs(5) != "YES" && state.dataIPShortCut->cAlphaArgs(5) != "NO") {
   10504           0 :                 ErrorsFound = true;
   10505           0 :                 ShowSevereError(state,
   10506           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
   10507           0 :                                     state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\"");
   10508             :             }
   10509             : 
   10510             :             // Error if Airflow Control Type = ScheduledOnly and Airflow Has Multiplier Schedule = No
   10511           8 :             if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULEDONLY" && state.dataIPShortCut->cAlphaArgs(5) == "NO") {
   10512           0 :                 ErrorsFound = true;
   10513           0 :                 ShowSevereError(state,
   10514           0 :                                 cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
   10515           0 :                                     state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10516           0 :                 ShowContinueError(state, "..when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\"");
   10517             :             }
   10518             : 
   10519             :             // Warning if Airflow Control Type = AlwaysOnAtMaxFlow and Airflow Has Multiplier Schedule = Yes
   10520           8 :             if (state.dataIPShortCut->cAlphaArgs(4) == "ALWAYSONATMAXIMUMFLOW" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
   10521           0 :                 ShowWarningError(state,
   10522           0 :                                  cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "has " +
   10523           0 :                                      state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10524           0 :                 ShowContinueError(state,
   10525           0 :                                   "..but " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
   10526           0 :                                       "If specified, the " + state.dataIPShortCut->cAlphaFieldNames(5) + " will be ignored.");
   10527             :             }
   10528             : 
   10529             :             // Warning if Airflow Control Type = AlwaysOff and Airflow Has Multiplier Schedule = Yes
   10530           8 :             if (state.dataIPShortCut->cAlphaArgs(4) == "ALWAYSOFF" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
   10531           0 :                 ShowWarningError(state,
   10532           0 :                                  cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "has " +
   10533           0 :                                      state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10534           0 :                 ShowContinueError(state,
   10535           0 :                                   "..but " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
   10536           0 :                                       "\". If specified, the " + state.dataIPShortCut->cAlphaFieldNames(5) + " will be ignored.");
   10537             :             }
   10538             : 
   10539           8 :             if (SurfNum > 0) {
   10540           8 :                 state.dataSurface->AirflowWindows = true;
   10541           8 :                 state.dataSurface->SurfWinAirflowSource(SurfNum) =
   10542          16 :                     static_cast<WindowAirFlowSource>(getEnumerationValue(WindowAirFlowSourceNamesUC, state.dataIPShortCut->cAlphaArgs(2)));
   10543             : 
   10544           8 :                 state.dataSurface->SurfWinAirflowDestination(SurfNum) =
   10545          16 :                     static_cast<WindowAirFlowDestination>(getEnumerationValue(WindowAirFlowDestinationNamesUC, state.dataIPShortCut->cAlphaArgs(3)));
   10546             : 
   10547           8 :                 if (state.dataSurface->SurfWinAirflowDestination(SurfNum) == WindowAirFlowDestination::Return) {
   10548           0 :                     int controlledZoneNum = DataZoneEquipment::GetControlledZoneIndex(state, state.dataSurface->Surface(SurfNum).ZoneName);
   10549           0 :                     if (controlledZoneNum > 0) {
   10550           0 :                         state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).HasAirFlowWindowReturn = true;
   10551             :                     }
   10552             : 
   10553             :                     // Set return air node number
   10554           0 :                     state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) = 0;
   10555           0 :                     std::string retNodeName = "";
   10556           0 :                     if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) {
   10557           0 :                         retNodeName = state.dataIPShortCut->cAlphaArgs(7);
   10558             :                     }
   10559           0 :                     std::string callDescription = cCurrentModuleObject + "=" + state.dataSurface->Surface(SurfNum).Name;
   10560           0 :                     state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) =
   10561           0 :                         DataZoneEquipment::GetReturnAirNodeForZone(state, state.dataSurface->Surface(SurfNum).Zone, retNodeName, callDescription);
   10562           0 :                     if (state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) == 0) {
   10563           0 :                         ShowSevereError(state,
   10564           0 :                                         std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataSurface->Surface(SurfNum).Name +
   10565           0 :                                             "\", airflow window return air node not found for " + state.dataIPShortCut->cAlphaFieldNames(3) + " = " +
   10566           0 :                                             state.dataIPShortCut->cAlphaArgs(3));
   10567           0 :                         if (!state.dataIPShortCut->lAlphaFieldBlanks(7))
   10568           0 :                             ShowContinueError(state,
   10569           0 :                                               state.dataIPShortCut->cAlphaFieldNames(7) + "=\"" + state.dataIPShortCut->cAlphaArgs(7) +
   10570             :                                                   "\" did not find a matching return air node.");
   10571           0 :                         ShowContinueError(state,
   10572             :                                           "..Airflow windows with Airflow Destination = ReturnAir must reference a controlled Zone (appear in a "
   10573             :                                           "ZoneHVAC:EquipmentConnections object) with at least one return air node.");
   10574           0 :                         ErrorsFound = true;
   10575             :                     }
   10576             :                 }
   10577           8 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "AlwaysOnAtMaximumFlow")) {
   10578           8 :                     state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::MaxFlow;
   10579           0 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "AlwaysOff")) {
   10580           0 :                     state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::AlwaysOff;
   10581           0 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "ScheduledOnly")) {
   10582           0 :                     state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::Schedule;
   10583             :                 }
   10584           8 :                 state.dataSurface->SurfWinMaxAirflow(SurfNum) = state.dataIPShortCut->rNumericArgs(1);
   10585           8 :                 if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULEDONLY" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
   10586           0 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
   10587           0 :                         ErrorsFound = true;
   10588           0 :                         ShowSevereError(state,
   10589           0 :                                         cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", has " +
   10590           0 :                                             state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
   10591           0 :                         ShowContinueError(state,
   10592           0 :                                           "..and " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
   10593           0 :                                               "\", but no " + state.dataIPShortCut->cAlphaFieldNames(6) + " specified.");
   10594             :                     } else {
   10595           0 :                         state.dataSurface->SurfWinAirflowHasSchedule(SurfNum) = true;
   10596           0 :                         state.dataSurface->SurfWinAirflowSchedulePtr(SurfNum) = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
   10597           0 :                         if (state.dataSurface->SurfWinAirflowSchedulePtr(SurfNum) == 0) {
   10598           0 :                             ErrorsFound = true;
   10599           0 :                             ShowSevereError(state,
   10600           0 :                                             cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
   10601           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" + state.dataIPShortCut->cAlphaArgs(6) + "\"");
   10602             :                         }
   10603             :                     }
   10604             :                 }
   10605             :                 // Warning if associated window is an interior window
   10606           8 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond != ExternalEnvironment && !ErrorsFound)
   10607           0 :                     ShowWarningError(state,
   10608           0 :                                      cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
   10609             :                                          "\", is an Interior window; cannot be an airflow window.");
   10610           8 :                 if (!ErrorsFound) {
   10611             :                     // Require that gas in airflow gap has type = air
   10612           8 :                     MatGapFlow = state.dataConstruction->Construct(ConstrNum).LayerPoint(2);
   10613           8 :                     if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers == 3)
   10614           4 :                         MatGapFlow = state.dataConstruction->Construct(ConstrNum).LayerPoint(4);
   10615           8 :                     if (state.dataMaterial->Material(MatGapFlow).GasType(1) != 1) {
   10616           0 :                         ErrorsFound = true;
   10617           0 :                         ShowSevereError(state,
   10618           0 :                                         cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
   10619           0 :                                             "\", Gas type not air in airflow gap of construction " +
   10620           0 :                                             state.dataConstruction->Construct(ConstrNum).Name);
   10621             :                     }
   10622             :                     // Require that gas be air in airflow gaps on either side of a between glass shade/blind
   10623           8 :                     if (state.dataSurface->Surface(SurfNum).HasShadeControl) {
   10624           4 :                         for (std::size_t listIndex = 0; listIndex < state.dataSurface->Surface(SurfNum).windowShadingControlList.size();
   10625             :                              ++listIndex) {
   10626           4 :                             int WSCPtr = state.dataSurface->Surface(SurfNum).windowShadingControlList[listIndex];
   10627           4 :                             if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
   10628           4 :                                 ConstrNumSh = state.dataSurface->Surface(SurfNum).shadedConstructionList[listIndex];
   10629           4 :                                 if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers == 2) {
   10630           2 :                                     MatGapFlow1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2);
   10631           2 :                                     MatGapFlow2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(4);
   10632             :                                 } else {
   10633           2 :                                     MatGapFlow1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(4);
   10634           2 :                                     MatGapFlow2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(6);
   10635             :                                 }
   10636           8 :                                 if (state.dataMaterial->Material(MatGapFlow1).GasType(1) != 1 ||
   10637           4 :                                     state.dataMaterial->Material(MatGapFlow2).GasType(1) != 1) {
   10638           0 :                                     ErrorsFound = true;
   10639           0 :                                     ShowSevereError(state,
   10640           0 :                                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
   10641             :                                                         "\", gas type must be air on either side of the shade/blind");
   10642             :                                 }
   10643           4 :                                 break; // only need the first window shading control since they should be the same
   10644             :                             }
   10645             :                         }
   10646             :                     }
   10647             :                 }
   10648             :             }
   10649             : 
   10650             :         } // End of loop over window airflow controls
   10651             :     }
   10652             : 
   10653         771 :     void GetFoundationData(EnergyPlusData &state, bool &ErrorsFound)
   10654             :     {
   10655             : 
   10656             :         int NumAlphas;
   10657             :         int NumProps;
   10658             :         int IOStat;
   10659         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   10660             : 
   10661             :         // Read Kiva Settings
   10662         771 :         cCurrentModuleObject = "Foundation:Kiva:Settings";
   10663         771 :         int TotKivaStgs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   10664             : 
   10665         771 :         if (TotKivaStgs > 1) {
   10666           0 :             ErrorsFound = true;
   10667           0 :             ShowSevereError(state, "Multiple " + cCurrentModuleObject + " objects found. Only one is allowed.");
   10668             :         }
   10669             : 
   10670         771 :         if (TotKivaStgs == 1) {
   10671          35 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   10672             :                                                                      cCurrentModuleObject,
   10673             :                                                                      1,
   10674           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
   10675             :                                                                      NumAlphas,
   10676           5 :                                                                      state.dataIPShortCut->rNumericArgs,
   10677             :                                                                      NumProps,
   10678             :                                                                      IOStat,
   10679           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   10680           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   10681           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   10682           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   10683             : 
   10684           5 :             int numF = 1;
   10685           5 :             int alpF = 1;
   10686             : 
   10687           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10688           5 :                 state.dataSurfaceGeometry->kivaManager.settings.soilK = state.dataIPShortCut->rNumericArgs(numF);
   10689             :             }
   10690           5 :             numF++;
   10691           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10692           5 :                 state.dataSurfaceGeometry->kivaManager.settings.soilRho = state.dataIPShortCut->rNumericArgs(numF);
   10693             :             }
   10694           5 :             numF++;
   10695           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10696           5 :                 state.dataSurfaceGeometry->kivaManager.settings.soilCp = state.dataIPShortCut->rNumericArgs(numF);
   10697             :             }
   10698           5 :             numF++;
   10699           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10700           5 :                 state.dataSurfaceGeometry->kivaManager.settings.groundSolarAbs = state.dataIPShortCut->rNumericArgs(numF);
   10701             :             }
   10702           5 :             numF++;
   10703           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10704           5 :                 state.dataSurfaceGeometry->kivaManager.settings.groundThermalAbs = state.dataIPShortCut->rNumericArgs(numF);
   10705             :             }
   10706           5 :             numF++;
   10707           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10708           5 :                 state.dataSurfaceGeometry->kivaManager.settings.groundRoughness = state.dataIPShortCut->rNumericArgs(numF);
   10709             :             }
   10710           5 :             numF++;
   10711           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10712           5 :                 state.dataSurfaceGeometry->kivaManager.settings.farFieldWidth = state.dataIPShortCut->rNumericArgs(numF);
   10713             :             }
   10714           5 :             numF++;
   10715             : 
   10716           5 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   10717           5 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "ZeroFlux")) {
   10718           1 :                     state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::ZERO_FLUX;
   10719           4 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "GroundWater")) {
   10720           0 :                     state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::GROUNDWATER;
   10721           4 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "Autoselect")) {
   10722           4 :                     state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::AUTO;
   10723             :                 } else {
   10724           0 :                     ErrorsFound = true;
   10725           0 :                     ShowSevereError(state,
   10726           0 :                                     format("{}, {} is not a valid choice for {}",
   10727             :                                            cCurrentModuleObject,
   10728           0 :                                            state.dataIPShortCut->cAlphaArgs(alpF),
   10729           0 :                                            state.dataIPShortCut->cAlphaFieldNames(alpF)));
   10730             :                 }
   10731             :             }
   10732           5 :             alpF++;
   10733             : 
   10734           5 :             if (state.dataIPShortCut->lNumericFieldBlanks(numF) || state.dataIPShortCut->rNumericArgs(numF) == DataGlobalConstants::AutoCalculate) {
   10735             :                 // Autocalculate deep-ground depth (see KivaManager::defineDefaultFoundation() for actual calculation)
   10736           4 :                 state.dataSurfaceGeometry->kivaManager.settings.deepGroundDepth = 40.0;
   10737           4 :                 state.dataSurfaceGeometry->kivaManager.settings.autocalculateDeepGroundDepth = true;
   10738           4 :                 if (state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary != HeatBalanceKivaManager::KivaManager::Settings::AUTO) {
   10739           0 :                     ErrorsFound = true;
   10740           0 :                     ShowSevereError(state,
   10741           0 :                                     format("{}, {} should not be set to Autocalculate unless {} is set to Autoselect",
   10742             :                                            cCurrentModuleObject,
   10743           0 :                                            state.dataIPShortCut->cNumericFieldNames(numF),
   10744           0 :                                            state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   10745             :                 }
   10746             :             } else {
   10747           1 :                 state.dataSurfaceGeometry->kivaManager.settings.deepGroundDepth = state.dataIPShortCut->rNumericArgs(numF);
   10748           1 :                 state.dataSurfaceGeometry->kivaManager.settings.autocalculateDeepGroundDepth = false;
   10749             :             }
   10750           5 :             numF++;
   10751           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10752           1 :                 state.dataSurfaceGeometry->kivaManager.settings.minCellDim = state.dataIPShortCut->rNumericArgs(numF);
   10753             :             }
   10754           5 :             numF++;
   10755           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10756           1 :                 state.dataSurfaceGeometry->kivaManager.settings.maxGrowthCoeff = state.dataIPShortCut->rNumericArgs(numF);
   10757             :             }
   10758           5 :             numF++;
   10759             : 
   10760           5 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   10761           1 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "Hourly")) {
   10762           1 :                     state.dataSurfaceGeometry->kivaManager.settings.timestepType = HeatBalanceKivaManager::KivaManager::Settings::HOURLY;
   10763           1 :                     state.dataSurfaceGeometry->kivaManager.timestep = 3600.; // seconds
   10764             :                 } else { // if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs( alpF ), "Timestep"))
   10765           0 :                     state.dataSurfaceGeometry->kivaManager.settings.timestepType = HeatBalanceKivaManager::KivaManager::Settings::TIMESTEP;
   10766           0 :                     state.dataSurfaceGeometry->kivaManager.timestep = state.dataGlobal->MinutesPerTimeStep * 60.;
   10767             :                 }
   10768             :             }
   10769           5 :             alpF++;
   10770             :         }
   10771             : 
   10772             :         // Set default foundation (probably doesn't need to be called if there are no Kiva
   10773             :         // surfaces, but we don't know that yet). We call this here so that the default
   10774             :         // foundation is available for 1) the starting copy for user-defined Foundation:Kiva
   10775             :         // object default inputs, and 2) the actual default Foundation object if a
   10776             :         // user-defined Foundation:Kiva name is not referenced by a surface.
   10777         771 :         state.dataSurfaceGeometry->kivaManager.defineDefaultFoundation(state);
   10778             : 
   10779             :         // Read Foundation objects
   10780         771 :         cCurrentModuleObject = "Foundation:Kiva";
   10781         771 :         int TotKivaFnds = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   10782             : 
   10783         771 :         if (TotKivaFnds > 0) {
   10784          14 :             for (int Loop = 1; Loop <= TotKivaFnds; ++Loop) {
   10785          49 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   10786             :                                                                          cCurrentModuleObject,
   10787             :                                                                          Loop,
   10788           7 :                                                                          state.dataIPShortCut->cAlphaArgs,
   10789             :                                                                          NumAlphas,
   10790           7 :                                                                          state.dataIPShortCut->rNumericArgs,
   10791             :                                                                          NumProps,
   10792             :                                                                          IOStat,
   10793           7 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
   10794           7 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
   10795           7 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
   10796           7 :                                                                          state.dataIPShortCut->cNumericFieldNames);
   10797             : 
   10798           7 :                 int numF = 1;
   10799           7 :                 int alpF = 1;
   10800             : 
   10801           7 :                 bool ErrorInName = false;
   10802             : 
   10803          14 :                 HeatBalanceKivaManager::FoundationKiva fndInput;
   10804             : 
   10805           7 :                 fndInput.name = state.dataIPShortCut->cAlphaArgs(alpF);
   10806           7 :                 alpF++;
   10807           7 :                 UtilityRoutines::IsNameEmpty(state, fndInput.name, cCurrentModuleObject, ErrorInName);
   10808           7 :                 if (ErrorInName) {
   10809           0 :                     ErrorsFound = true;
   10810           0 :                     continue;
   10811             :                 }
   10812             : 
   10813             :                 // Start with copy of default
   10814           7 :                 auto &fnd = fndInput.foundation;
   10815           7 :                 fnd = state.dataSurfaceGeometry->kivaManager.defaultFoundation.foundation;
   10816             : 
   10817             :                 // Indoor temperature
   10818           7 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10819           1 :                     fndInput.assumedIndoorTemperature = state.dataIPShortCut->rNumericArgs(numF);
   10820             :                 } else {
   10821           6 :                     fndInput.assumedIndoorTemperature = -9999;
   10822             :                 }
   10823           7 :                 numF++;
   10824             : 
   10825             :                 // Interior horizontal insulation
   10826           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   10827           3 :                     int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   10828           3 :                     if (index == 0) {
   10829           0 :                         ErrorsFound = true;
   10830           0 :                         ShowSevereError(state,
   10831           0 :                                         "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   10832           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) +
   10833           0 :                                             ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
   10834           0 :                         continue;
   10835             :                     }
   10836           3 :                     auto &m = state.dataMaterial->Material(index);
   10837           3 :                     if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
   10838           0 :                         ErrorsFound = true;
   10839           0 :                         ShowSevereError(state,
   10840           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   10841           0 :                                             "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   10842           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   10843           0 :                         continue;
   10844             :                     }
   10845           3 :                     fndInput.intHIns.x = 0.0;
   10846           3 :                     fndInput.intHIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
   10847           3 :                     fndInput.intHIns.depth = m.Thickness;
   10848             :                 }
   10849           7 :                 alpF++;
   10850             : 
   10851           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   10852           3 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10853           3 :                         fndInput.intHIns.z = 0.0;
   10854             :                     } else {
   10855           0 :                         fndInput.intHIns.z = state.dataIPShortCut->rNumericArgs(numF);
   10856             :                     }
   10857           3 :                     numF++;
   10858           3 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10859           0 :                         ErrorsFound = true;
   10860           0 :                         ShowSevereError(state,
   10861           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10862           0 :                                             " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
   10863           0 :                         continue;
   10864             :                     } else {
   10865           3 :                         fndInput.intHIns.width = -state.dataIPShortCut->rNumericArgs(numF);
   10866             :                     }
   10867           3 :                     numF++;
   10868             :                 } else {
   10869           4 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10870           0 :                         ShowWarningError(state,
   10871           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10872             :                                              " defined");
   10873           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   10874             :                     }
   10875           4 :                     numF++;
   10876           4 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10877           0 :                         ShowWarningError(state,
   10878           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10879             :                                              " defined");
   10880           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   10881             :                     }
   10882           4 :                     numF++;
   10883             :                 }
   10884             : 
   10885             :                 // Interior vertical insulation
   10886           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   10887           0 :                     int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   10888           0 :                     if (index == 0) {
   10889           0 :                         ErrorsFound = true;
   10890           0 :                         ShowSevereError(state,
   10891           0 :                                         "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   10892           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) +
   10893           0 :                                             ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
   10894           0 :                         continue;
   10895             :                     }
   10896           0 :                     auto &m = state.dataMaterial->Material(index);
   10897           0 :                     if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
   10898           0 :                         ErrorsFound = true;
   10899           0 :                         ShowSevereError(state,
   10900           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   10901           0 :                                             "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   10902           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   10903           0 :                         continue;
   10904             :                     }
   10905           0 :                     fndInput.intVIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
   10906           0 :                     fndInput.intVIns.width = -m.Thickness;
   10907           0 :                     fndInput.intVIns.x = 0.0;
   10908           0 :                     fndInput.intVIns.z = 0.0;
   10909             :                 }
   10910           7 :                 alpF++;
   10911             : 
   10912           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   10913           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10914           0 :                         ErrorsFound = true;
   10915           0 :                         ShowSevereError(state,
   10916           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10917           0 :                                             " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
   10918           0 :                         continue;
   10919             :                     } else {
   10920           0 :                         fndInput.intVIns.depth = state.dataIPShortCut->rNumericArgs(numF);
   10921             :                     }
   10922           0 :                     numF++;
   10923             :                 } else {
   10924           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10925           0 :                         ShowWarningError(state,
   10926           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10927             :                                              " defined");
   10928           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   10929             :                     }
   10930           7 :                     numF++;
   10931             :                 }
   10932             : 
   10933             :                 // Exterior horizontal insulation
   10934           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   10935           0 :                     int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   10936           0 :                     if (index == 0) {
   10937           0 :                         ErrorsFound = true;
   10938           0 :                         ShowSevereError(state,
   10939           0 :                                         "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   10940           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) +
   10941           0 :                                             ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
   10942           0 :                         continue;
   10943             :                     }
   10944           0 :                     auto &m = state.dataMaterial->Material(index);
   10945           0 :                     if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
   10946           0 :                         ErrorsFound = true;
   10947           0 :                         ShowSevereError(state,
   10948           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   10949           0 :                                             "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   10950           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   10951           0 :                         continue;
   10952             :                     }
   10953           0 :                     fndInput.extHIns.x = 0.0;
   10954           0 :                     fndInput.extHIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
   10955           0 :                     fndInput.extHIns.depth = m.Thickness;
   10956             :                 }
   10957           7 :                 alpF++;
   10958             : 
   10959           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   10960           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10961           0 :                         fndInput.extHIns.z = 0.0;
   10962             :                     } else {
   10963           0 :                         fndInput.extHIns.z = state.dataIPShortCut->rNumericArgs(numF);
   10964             :                     }
   10965           0 :                     numF++;
   10966           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10967           0 :                         ErrorsFound = true;
   10968           0 :                         ShowSevereError(state,
   10969           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10970           0 :                                             " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
   10971           0 :                         continue;
   10972             :                     } else {
   10973           0 :                         fndInput.extHIns.width = state.dataIPShortCut->rNumericArgs(numF);
   10974             :                     }
   10975           0 :                     numF++;
   10976             :                 } else {
   10977           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10978           0 :                         ShowWarningError(state,
   10979           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10980             :                                              " defined");
   10981           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   10982             :                     }
   10983           7 :                     numF++;
   10984           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   10985           0 :                         ShowWarningError(state,
   10986           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   10987             :                                              " defined");
   10988           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   10989             :                     }
   10990           7 :                     numF++;
   10991             :                 }
   10992             : 
   10993             :                 // Exterior vertical insulation
   10994           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   10995           4 :                     int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   10996           4 :                     if (index == 0) {
   10997           0 :                         ErrorsFound = true;
   10998           0 :                         ShowSevereError(state,
   10999           0 :                                         "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   11000           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11001           0 :                                             ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
   11002           0 :                         continue;
   11003             :                     }
   11004           4 :                     auto &m = state.dataMaterial->Material(index);
   11005           4 :                     if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
   11006           0 :                         ErrorsFound = true;
   11007           0 :                         ShowSevereError(state,
   11008           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11009           0 :                                             "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   11010           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11011           0 :                         continue;
   11012             :                     }
   11013           4 :                     fndInput.extVIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
   11014           4 :                     fndInput.extVIns.width = m.Thickness;
   11015           4 :                     fndInput.extVIns.x = 0.0;
   11016           4 :                     fndInput.extVIns.z = 0.0;
   11017             :                 }
   11018           7 :                 alpF++;
   11019             : 
   11020           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11021           4 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11022           0 :                         ErrorsFound = true;
   11023           0 :                         ShowSevereError(state,
   11024           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   11025           0 :                                             " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
   11026           0 :                         continue;
   11027             :                     } else {
   11028           4 :                         fndInput.extVIns.depth = state.dataIPShortCut->rNumericArgs(numF);
   11029             :                     }
   11030           4 :                     numF++;
   11031             :                 } else {
   11032           3 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11033           0 :                         ShowWarningError(state,
   11034           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   11035             :                                              " defined");
   11036           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   11037             :                     }
   11038           3 :                     numF++;
   11039             :                 }
   11040             : 
   11041             :                 // Foundation wall
   11042           7 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11043           7 :                     fnd.wall.heightAboveGrade = state.dataIPShortCut->rNumericArgs(numF);
   11044             :                 }
   11045           7 :                 numF++;
   11046             : 
   11047           7 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11048           7 :                     fnd.wall.depthBelowSlab = state.dataIPShortCut->rNumericArgs(numF);
   11049             :                 }
   11050           7 :                 numF++;
   11051             : 
   11052           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11053           0 :                     fndInput.wallConstructionIndex =
   11054           0 :                         UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataConstruction->Construct);
   11055           0 :                     if (fndInput.wallConstructionIndex == 0) {
   11056           0 :                         ErrorsFound = true;
   11057           0 :                         ShowSevereError(state,
   11058           0 :                                         "Did not find matching construction for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   11059           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11060           0 :                                             ", missing construction = " + state.dataIPShortCut->cAlphaArgs(alpF));
   11061           0 :                         continue;
   11062             :                     }
   11063           0 :                     auto &c = state.dataConstruction->Construct(fndInput.wallConstructionIndex);
   11064           0 :                     c.IsUsed = true;
   11065           0 :                     if (c.TypeIsWindow) {
   11066           0 :                         ErrorsFound = true;
   11067           0 :                         ShowSevereError(state,
   11068           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11069           0 :                                             "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   11070           0 :                         ShowContinueError(state, "Cannot be a window construction");
   11071           0 :                         continue;
   11072             :                     }
   11073             :                 } else {
   11074           7 :                     fndInput.wallConstructionIndex = 0; // Use default wall construction
   11075             :                 }
   11076           7 :                 alpF++;
   11077             : 
   11078             :                 // Footing
   11079           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11080           0 :                     int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11081           0 :                     if (index == 0) {
   11082           0 :                         ErrorsFound = true;
   11083           0 :                         ShowSevereError(state,
   11084           0 :                                         "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   11085           0 :                                             state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11086           0 :                                             ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
   11087           0 :                         continue;
   11088             :                     }
   11089           0 :                     auto &m = state.dataMaterial->Material(index);
   11090           0 :                     if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
   11091           0 :                         ErrorsFound = true;
   11092           0 :                         ShowSevereError(state,
   11093           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11094           0 :                                             "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   11095           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11096           0 :                         continue;
   11097             :                     }
   11098           0 :                     fndInput.footing.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
   11099           0 :                     fndInput.footing.width = m.Thickness;
   11100           0 :                     fndInput.footing.x = 0.0;
   11101           0 :                     fndInput.footing.z = 0.0;
   11102             :                 }
   11103           7 :                 alpF++;
   11104             : 
   11105           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11106           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11107           0 :                         ErrorsFound = true;
   11108           0 :                         ShowSevereError(state,
   11109           0 :                                         cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   11110           0 :                                             " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
   11111           0 :                         continue;
   11112             :                     } else {
   11113           0 :                         fndInput.footing.depth = state.dataIPShortCut->rNumericArgs(numF);
   11114             :                     }
   11115           0 :                     numF++;
   11116             :                 } else {
   11117           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11118           0 :                         ShowWarningError(state,
   11119           0 :                                          cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   11120             :                                              " defined");
   11121           0 :                         ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
   11122             :                     }
   11123           7 :                     numF++;
   11124             :                 }
   11125             : 
   11126             :                 // General Blocks
   11127           7 :                 int numRemainingFields = NumAlphas - (alpF - 1) + NumProps - (numF - 1);
   11128           7 :                 if (numRemainingFields > 0) {
   11129           0 :                     int numBlocks = numRemainingFields / 4;
   11130           0 :                     if (mod(numRemainingFields, 4) != 0) {
   11131           0 :                         ShowWarningError(state,
   11132           0 :                                          format("{}=\"{}\", number of Block fields not even multiple of 4. Will read in {}",
   11133             :                                                 cCurrentModuleObject,
   11134             :                                                 fndInput.name,
   11135           0 :                                                 numBlocks));
   11136             :                     }
   11137           0 :                     for (int blockNum = 0; blockNum < numBlocks; blockNum++) {
   11138           0 :                         Kiva::InputBlock block;
   11139           0 :                         if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11140           0 :                             int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11141           0 :                             if (index == 0) {
   11142           0 :                                 ErrorsFound = true;
   11143           0 :                                 ShowSevereError(state,
   11144           0 :                                                 "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
   11145           0 :                                                     state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11146           0 :                                                     ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
   11147           0 :                                 continue;
   11148             :                             }
   11149           0 :                             auto &m = state.dataMaterial->Material(index);
   11150           0 :                             if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
   11151           0 :                                 ErrorsFound = true;
   11152           0 :                                 ShowSevereError(state,
   11153           0 :                                                 cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " +
   11154           0 :                                                     state.dataIPShortCut->cAlphaFieldNames(alpF) + "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
   11155           0 :                                 ShowContinueError(state, "Must be of type \"Material\"");
   11156           0 :                                 continue;
   11157             :                             }
   11158           0 :                             block.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
   11159           0 :                             block.width = m.Thickness;
   11160             :                         } else {
   11161           0 :                             ErrorsFound = true;
   11162           0 :                             ShowSevereError(state,
   11163           0 :                                             cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
   11164             :                                                 " is required and not given.");
   11165           0 :                             continue;
   11166             :                         }
   11167           0 :                         alpF++;
   11168             : 
   11169           0 :                         if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11170           0 :                             block.depth = 0.0; // Temporary indicator to default to foundation depth
   11171             :                         } else {
   11172           0 :                             block.depth = state.dataIPShortCut->rNumericArgs(numF);
   11173             :                         }
   11174           0 :                         numF++;
   11175             : 
   11176           0 :                         if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11177           0 :                             ErrorsFound = true;
   11178           0 :                             ShowSevereError(state,
   11179           0 :                                             cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
   11180           0 :                                                 " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
   11181           0 :                             continue;
   11182             :                         } else {
   11183           0 :                             block.x = state.dataIPShortCut->rNumericArgs(numF);
   11184             :                         }
   11185           0 :                         numF++;
   11186             : 
   11187           0 :                         if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11188           0 :                             block.z = 0.0;
   11189             :                         } else {
   11190           0 :                             block.z = state.dataIPShortCut->rNumericArgs(numF);
   11191             :                         }
   11192           0 :                         numF++;
   11193             : 
   11194           0 :                         fnd.inputBlocks.push_back(block);
   11195             :                     }
   11196             :                 }
   11197             : 
   11198           7 :                 state.dataSurfaceGeometry->kivaManager.foundationInputs.push_back(fndInput);
   11199             :             }
   11200             :         }
   11201         771 :     }
   11202             : 
   11203         771 :     void GetOSCData(EnergyPlusData &state, bool &ErrorsFound)
   11204             :     {
   11205             : 
   11206             :         // SUBROUTINE INFORMATION:
   11207             :         //       AUTHOR         Linda Lawrie
   11208             :         //       DATE WRITTEN   May 2000
   11209             :         //       MODIFIED       Jul 2011, M.J. Witte and C.O. Pedersen, add new fields to OSC for last T, max and min
   11210             :         //       RE-ENGINEERED  na
   11211             : 
   11212             :         // PURPOSE OF THIS SUBROUTINE:
   11213             :         // This subroutine gets the OtherSideCoefficient data.
   11214             : 
   11215             :         // METHODOLOGY EMPLOYED:
   11216             :         // na
   11217             : 
   11218             :         // REFERENCES:
   11219             :         // Other Side Coefficient Definition
   11220             :         // OtherSideCoefficients,
   11221             :         //       \memo This object sets the other side conditions for a surface in a variety of ways.
   11222             :         //   A1, \field OtherSideCoeff Name
   11223             :         //       \required-field
   11224             :         //       \reference OSCNames
   11225             :         //       \reference OutFaceEnvNames
   11226             :         //   N1, \field Combined convective/radiative film coefficient
   11227             :         //       \required-field
   11228             :         //       \type real
   11229             :         //       \note if>0, N1 becomes exterior convective/radiative film coefficient and other fields
   11230             :         //       \note are used to calc outside air temp then exterior surface temp based on outside air
   11231             :         //       \note and specified coefficient
   11232             :         //       \note if<=0, then remaining fields calculate the outside surface temperature(?)
   11233             :         //       \note following fields are used in the equation:
   11234             :         //       \note SurfTemp=N7*TempZone + N4*OutsideDryBulb + N2*N3 + GroundTemp*N5 + WindSpeed*N6*OutsideDryBulb
   11235             :         //   N2, \field User selected Constant Temperature
   11236             :         //       \units C
   11237             :         //       \type real
   11238             :         //       \note This parameter will be overwritten by the values from the schedule(A2 below) if one is present
   11239             :         //   N3, \field Coefficient modifying the user selected constant temperature
   11240             :         //       \note This coefficient is used even with a schedule.  It should normally be 1.0 in that case
   11241             :         //   N4, \field Coefficient modifying the external dry bulb temperature
   11242             :         //       \type real
   11243             :         //   N5, \field Coefficient modifying the ground temperature
   11244             :         //       \type real
   11245             :         //   N6, \field Coefficient modifying the wind speed term (s/m)
   11246             :         //       \type real
   11247             :         //   N7, \field Coefficient modifying the zone air temperature part of the equation
   11248             :         //       \type real
   11249             :         //   A2, \field ScheduleName for constant temperature
   11250             :         //       \note Name of Schedule for values of "const" temperature.
   11251             :         //       \note Schedule values replace N2 - User selected constant temperature.
   11252             :         //       \type object-list
   11253             :         //       \object-list ScheduleNames
   11254             :         //   A3, \field Sinusoidal Variation of Constant Temperature Coefficient
   11255             :         //       \note Optionally used to vary Constant Temperature Coefficient with unitary sine wave
   11256             :         //       \type choice
   11257             :         //       \key Yes
   11258             :         //       \key No
   11259             :         //       \default No
   11260             :         //   N8; \field Period of Sinusoidal Variation
   11261             :         //       \note Use with sinusoidal variation to define the time period
   11262             :         //       \type real
   11263             :         //       \units hr
   11264             :         //       \default 24
   11265             :         //  N9, \field Previous Other Side Temperature Coefficient
   11266             :         //      \note This coeffient multiplies the other side temperature result from the
   11267             :         //      \note previous zone timestep
   11268             :         //      \type real
   11269             :         //      \default 0
   11270             :         // N10, \field Minimum Other Side Temperature
   11271             :         //      \type real
   11272             :         //      \units C
   11273             :         //      \default -100
   11274             :         // N11; \field Maximum Other Side Temperature
   11275             :         //      \type real
   11276             :         //      \units C
   11277             :         //      \default 200
   11278             : 
   11279             :         // Using/Aliasing
   11280             : 
   11281             :         using ScheduleManager::GetScheduleIndex;
   11282             : 
   11283             :         // Locals
   11284             :         // SUBROUTINE ARGUMENT DEFINITIONS:
   11285             : 
   11286             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11287             :         int NumAlphas;
   11288             :         int NumProps;
   11289             :         int Loop;
   11290             :         int IOStat;
   11291             :         int OSCNum;
   11292             :         bool ErrorInName;
   11293             :         bool IsBlank;
   11294        1542 :         std::string cOSCLimitsString;
   11295         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   11296             : 
   11297         771 :         cCurrentModuleObject = "SurfaceProperty:OtherSideCoefficients";
   11298         771 :         state.dataSurface->TotOSC = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11299         771 :         state.dataSurface->OSC.allocate(state.dataSurface->TotOSC);
   11300             : 
   11301         771 :         OSCNum = 0;
   11302         789 :         for (Loop = 1; Loop <= state.dataSurface->TotOSC; ++Loop) {
   11303         126 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   11304             :                                                                      cCurrentModuleObject,
   11305             :                                                                      Loop,
   11306          18 :                                                                      state.dataIPShortCut->cAlphaArgs,
   11307             :                                                                      NumAlphas,
   11308          18 :                                                                      state.dataIPShortCut->rNumericArgs,
   11309             :                                                                      NumProps,
   11310             :                                                                      IOStat,
   11311          18 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   11312          18 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   11313          18 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   11314          18 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   11315          18 :             ErrorInName = false;
   11316          18 :             IsBlank = false;
   11317          36 :             UtilityRoutines::VerifyName(
   11318          54 :                 state, state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->OSC, OSCNum, ErrorInName, IsBlank, cCurrentModuleObject + " Name");
   11319          18 :             if (ErrorInName) {
   11320           0 :                 ErrorsFound = true;
   11321           0 :                 continue;
   11322             :             }
   11323             : 
   11324          18 :             ++OSCNum;
   11325          18 :             state.dataSurface->OSC(OSCNum).Name = state.dataIPShortCut->cAlphaArgs(1);
   11326          18 :             state.dataSurface->OSC(OSCNum).SurfFilmCoef = state.dataIPShortCut->rNumericArgs(1);
   11327          18 :             state.dataSurface->OSC(OSCNum).ConstTemp = state.dataIPShortCut->rNumericArgs(2); //  This will be replaced if  schedule is used
   11328          18 :             state.dataSurface->OSC(OSCNum).ConstTempCoef =
   11329          18 :                 state.dataIPShortCut->rNumericArgs(3); //  This multiplier is used (even with schedule).  It should normally be 1.0
   11330          18 :             state.dataSurface->OSC(OSCNum).ExtDryBulbCoef = state.dataIPShortCut->rNumericArgs(4);
   11331          18 :             state.dataSurface->OSC(OSCNum).GroundTempCoef = state.dataIPShortCut->rNumericArgs(5);
   11332          18 :             state.dataSurface->OSC(OSCNum).WindSpeedCoef = state.dataIPShortCut->rNumericArgs(6);
   11333          18 :             state.dataSurface->OSC(OSCNum).ZoneAirTempCoef = state.dataIPShortCut->rNumericArgs(7);
   11334          18 :             state.dataSurface->OSC(OSCNum).SinusoidPeriod = state.dataIPShortCut->rNumericArgs(8);
   11335             : 
   11336          18 :             if ((!state.dataIPShortCut->lAlphaFieldBlanks(2)) && (NumAlphas != 1)) { //  Const temp will come from schedule specified below.
   11337          15 :                 state.dataSurface->OSC(OSCNum).ConstTempScheduleName = state.dataIPShortCut->cAlphaArgs(2);
   11338          15 :                 if (!state.dataSurface->OSC(OSCNum).ConstTempScheduleName.empty()) {
   11339          15 :                     state.dataSurface->OSC(OSCNum).ConstTempScheduleIndex =
   11340          15 :                         GetScheduleIndex(state, state.dataSurface->OSC(OSCNum).ConstTempScheduleName);
   11341          15 :                     if (state.dataSurface->OSC(OSCNum).ConstTempScheduleIndex == 0) {
   11342           0 :                         ShowSevereError(state,
   11343           0 :                                         cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
   11344           0 :                                             state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
   11345           0 :                         ErrorsFound = true;
   11346             :                     }
   11347             :                 }
   11348             :             }
   11349             : 
   11350          18 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
   11351             : 
   11352          15 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "No")) {
   11353          14 :                     state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef = false;
   11354           1 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "Yes")) {
   11355           1 :                     state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef = true;
   11356             :                 } else {
   11357           0 :                     ShowSevereError(state,
   11358           0 :                                     cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
   11359           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
   11360           0 :                     ErrorsFound = true;
   11361             :                 }
   11362             :             }
   11363             : 
   11364          18 :             if (state.dataIPShortCut->rNumericArgs(1) > 0.0 && !any_ne(state.dataIPShortCut->rNumericArgs({3, 7}), 0.0) &&
   11365           0 :                 (!state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef)) {
   11366           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" has zeros for all coefficients.");
   11367           0 :                 ShowContinueError(state, "...The outdoor air temperature for surfaces using this OtherSideCoefficients object will always be 0C.");
   11368             :             }
   11369             : 
   11370          19 :             if (state.dataIPShortCut->rNumericArgs(1) <= 0.0 && !any_ne(state.dataIPShortCut->rNumericArgs({3, 7}), 0.0) &&
   11371           1 :                 (!state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef)) {
   11372           0 :                 ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" has zeros for all coefficients.");
   11373           0 :                 ShowContinueError(state,
   11374             :                                   "...The outside surface temperature for surfaces using this OtherSideCoefficients object will always be 0C.");
   11375             :             }
   11376             : 
   11377          18 :             state.dataSurface->OSC(OSCNum).TPreviousCoef = state.dataIPShortCut->rNumericArgs(9);
   11378             : 
   11379          18 :             if (!state.dataIPShortCut->lNumericFieldBlanks(10)) {
   11380           1 :                 state.dataSurface->OSC(OSCNum).MinLimitPresent = true;
   11381           1 :                 state.dataSurface->OSC(OSCNum).MinTempLimit = state.dataIPShortCut->rNumericArgs(10);
   11382           1 :                 cOSCLimitsString = format("{:.3R}", state.dataIPShortCut->rNumericArgs(10));
   11383             :             } else {
   11384          17 :                 cOSCLimitsString = "N/A";
   11385             :             }
   11386          18 :             if (!state.dataIPShortCut->lNumericFieldBlanks(11)) {
   11387           1 :                 state.dataSurface->OSC(OSCNum).MaxLimitPresent = true;
   11388           1 :                 state.dataSurface->OSC(OSCNum).MaxTempLimit = state.dataIPShortCut->rNumericArgs(11);
   11389           1 :                 cOSCLimitsString += format(",{:.3R}", state.dataIPShortCut->rNumericArgs(10));
   11390             :             } else {
   11391          17 :                 cOSCLimitsString += ",N/A";
   11392             :             }
   11393             :         }
   11394             : 
   11395         789 :         for (Loop = 1; Loop <= state.dataSurface->TotOSC; ++Loop) {
   11396          18 :             if (Loop == 1) {
   11397             :                 static constexpr std::string_view OSCFormat1(
   11398             :                     "! <Other Side Coefficients>,Name,Combined convective/radiative film coefficient {W/m2-K},User selected "
   11399             :                     "Constant Temperature {C},Coefficient modifying the constant temperature term,Coefficient modifying the external "
   11400             :                     "dry bulb temperature term,Coefficient modifying the ground temperature term,Coefficient modifying the wind speed "
   11401             :                     "term {s/m},Coefficient modifying the zone air temperature term,Constant Temperature Schedule Name,Sinusoidal "
   11402             :                     "Variation,Period of Sinusoidal Variation,Previous Other Side Temperature Coefficient,Minimum Other Side "
   11403             :                     "Temperature {C},Maximum Other Side Temperature {C}");
   11404           8 :                 print(state.files.eio, "{}\n", OSCFormat1);
   11405             :             }
   11406          18 :             if (state.dataSurface->OSC(Loop).SurfFilmCoef > 0.0) {
   11407           1 :                 state.dataIPShortCut->cAlphaArgs(1) = format("{:.3R}", state.dataSurface->OSC(Loop).SurfFilmCoef);
   11408           4 :                 SetupOutputVariable(state,
   11409             :                                     "Surface Other Side Coefficients Exterior Air Drybulb Temperature",
   11410             :                                     OutputProcessor::Unit::C,
   11411           1 :                                     state.dataSurface->OSC(Loop).OSCTempCalc,
   11412             :                                     OutputProcessor::SOVTimeStepType::System,
   11413             :                                     OutputProcessor::SOVStoreType::Average,
   11414           2 :                                     state.dataSurface->OSC(Loop).Name);
   11415             :             } else {
   11416          17 :                 state.dataIPShortCut->cAlphaArgs(1) = "N/A";
   11417             :             }
   11418          18 :             if (state.dataSurface->OSC(Loop).ConstTempScheduleIndex != 0) {
   11419          15 :                 state.dataIPShortCut->cAlphaArgs(2) = state.dataSurface->OSC(Loop).ConstTempScheduleName;
   11420          15 :                 constexpr auto format{"Other Side Coefficients,{},{},{},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{},{},{:.3R},{:.3R},{}\n"};
   11421         180 :                 print(state.files.eio,
   11422             :                       format,
   11423          15 :                       state.dataSurface->OSC(Loop).Name,
   11424          15 :                       state.dataIPShortCut->cAlphaArgs(1),
   11425             :                       "N/A",
   11426          15 :                       state.dataSurface->OSC(Loop).ConstTempCoef,
   11427          15 :                       state.dataSurface->OSC(Loop).ExtDryBulbCoef,
   11428          15 :                       state.dataSurface->OSC(Loop).GroundTempCoef,
   11429          15 :                       state.dataSurface->OSC(Loop).WindSpeedCoef,
   11430          15 :                       state.dataSurface->OSC(Loop).ZoneAirTempCoef,
   11431          15 :                       state.dataIPShortCut->cAlphaArgs(2),
   11432          15 :                       state.dataIPShortCut->cAlphaArgs(3),
   11433          15 :                       state.dataSurface->OSC(Loop).SinusoidPeriod,
   11434          15 :                       state.dataSurface->OSC(Loop).TPreviousCoef,
   11435          15 :                       cOSCLimitsString);
   11436             :             } else {
   11437           3 :                 state.dataIPShortCut->cAlphaArgs(2) = "N/A";
   11438           3 :                 constexpr auto format{"Other Side Coefficients,{},{},{:.2R},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{},{},{:.3R},{:.3R},{}\n"};
   11439          39 :                 print(state.files.eio,
   11440             :                       format,
   11441           3 :                       state.dataSurface->OSC(Loop).Name,
   11442           3 :                       state.dataIPShortCut->cAlphaArgs(1),
   11443           3 :                       state.dataSurface->OSC(Loop).ConstTemp,
   11444           3 :                       state.dataSurface->OSC(Loop).ConstTempCoef,
   11445           3 :                       state.dataSurface->OSC(Loop).ExtDryBulbCoef,
   11446           3 :                       state.dataSurface->OSC(Loop).GroundTempCoef,
   11447           3 :                       state.dataSurface->OSC(Loop).WindSpeedCoef,
   11448           3 :                       state.dataSurface->OSC(Loop).ZoneAirTempCoef,
   11449           3 :                       state.dataIPShortCut->cAlphaArgs(2),
   11450           3 :                       state.dataIPShortCut->cAlphaArgs(3),
   11451           3 :                       state.dataSurface->OSC(Loop).SinusoidPeriod,
   11452           3 :                       state.dataSurface->OSC(Loop).TPreviousCoef,
   11453           3 :                       cOSCLimitsString);
   11454             :             }
   11455             :         }
   11456         771 :     }
   11457             : 
   11458         771 :     void GetOSCMData(EnergyPlusData &state, bool &ErrorsFound)
   11459             :     {
   11460             : 
   11461             :         // SUBROUTINE INFORMATION:
   11462             :         //       AUTHOR         Brent Griffith
   11463             :         //       DATE WRITTEN   November 2004
   11464             :         //       MODIFIED       na
   11465             :         //       RE-ENGINEERED  na
   11466             : 
   11467             :         // PURPOSE OF THIS SUBROUTINE:
   11468             :         // This subroutine gets the OtherSideConditionsModel data.
   11469             : 
   11470             :         // METHODOLOGY EMPLOYED:
   11471             :         // na
   11472             : 
   11473             :         // REFERENCES:
   11474             :         // derived from GetOSCData subroutine by Linda Lawrie
   11475             : 
   11476             :         //  OtherSideConditionsModel,
   11477             :         //      \memo This object sets up modifying the other side conditions for a surface from other model results.
   11478             :         //  A1, \field OtherSideConditionsModel Name
   11479             :         //      \required-field
   11480             :         //      \reference OSCMNames
   11481             :         //      \reference OutFaceEnvNames
   11482             :         //  A2; \field Type of Model to determine Boundary Conditions
   11483             :         //      \type choice
   11484             :         //      \key Transpired Collector
   11485             :         //      \key Vented PV Cavity
   11486             :         //      \key Hybrid PV Transpired Collector
   11487             : 
   11488             :         // Using/Aliasing
   11489             : 
   11490             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11491             :         int NumAlphas;
   11492             :         int NumProps;
   11493             :         int Loop;
   11494             :         int IOStat;
   11495             :         int OSCMNum;
   11496             :         bool ErrorInName;
   11497             :         bool IsBlank;
   11498         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   11499         771 :         cCurrentModuleObject = "SurfaceProperty:OtherSideConditionsModel";
   11500         771 :         state.dataSurface->TotOSCM = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11501         771 :         state.dataSurface->OSCM.allocate(state.dataSurface->TotOSCM);
   11502             :         // OSCM is already initialized in derived type defn.
   11503             : 
   11504         771 :         OSCMNum = 0;
   11505         791 :         for (Loop = 1; Loop <= state.dataSurface->TotOSCM; ++Loop) {
   11506          60 :             state.dataInputProcessing->inputProcessor->getObjectItem(
   11507          40 :                 state, cCurrentModuleObject, Loop, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumProps, IOStat);
   11508          20 :             ErrorInName = false;
   11509          20 :             IsBlank = false;
   11510          40 :             UtilityRoutines::VerifyName(
   11511          60 :                 state, state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->OSCM, OSCMNum, ErrorInName, IsBlank, cCurrentModuleObject + " Name");
   11512          20 :             if (ErrorInName) {
   11513           0 :                 ErrorsFound = true;
   11514           0 :                 continue;
   11515             :             }
   11516             : 
   11517          20 :             ++OSCMNum;
   11518          20 :             state.dataSurface->OSCM(OSCMNum).Name = state.dataIPShortCut->cAlphaArgs(1);
   11519             :             // Note no validation of the below at this time:
   11520          20 :             state.dataSurface->OSCM(OSCMNum).Class = state.dataIPShortCut->cAlphaArgs(2);
   11521             :             // setup output vars for modeled coefficients
   11522          80 :             SetupOutputVariable(state,
   11523             :                                 "Surface Other Side Conditions Modeled Convection Air Temperature",
   11524             :                                 OutputProcessor::Unit::C,
   11525          20 :                                 state.dataSurface->OSCM(OSCMNum).TConv,
   11526             :                                 OutputProcessor::SOVTimeStepType::System,
   11527             :                                 OutputProcessor::SOVStoreType::Average,
   11528          40 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11529          80 :             SetupOutputVariable(state,
   11530             :                                 "Surface Other Side Conditions Modeled Convection Heat Transfer Coefficient",
   11531             :                                 OutputProcessor::Unit::W_m2K,
   11532          20 :                                 state.dataSurface->OSCM(OSCMNum).HConv,
   11533             :                                 OutputProcessor::SOVTimeStepType::System,
   11534             :                                 OutputProcessor::SOVStoreType::Average,
   11535          40 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11536          80 :             SetupOutputVariable(state,
   11537             :                                 "Surface Other Side Conditions Modeled Radiation Temperature",
   11538             :                                 OutputProcessor::Unit::C,
   11539          20 :                                 state.dataSurface->OSCM(OSCMNum).TRad,
   11540             :                                 OutputProcessor::SOVTimeStepType::System,
   11541             :                                 OutputProcessor::SOVStoreType::Average,
   11542          40 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11543          80 :             SetupOutputVariable(state,
   11544             :                                 "Surface Other Side Conditions Modeled Radiation Heat Transfer Coefficient",
   11545             :                                 OutputProcessor::Unit::W_m2K,
   11546          20 :                                 state.dataSurface->OSCM(OSCMNum).HRad,
   11547             :                                 OutputProcessor::SOVTimeStepType::System,
   11548             :                                 OutputProcessor::SOVStoreType::Average,
   11549          40 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11550             : 
   11551          20 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
   11552           0 :                 SetupEMSActuator(state,
   11553             :                                  "Other Side Boundary Conditions",
   11554           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   11555             :                                  "Convection Bulk Air Temperature",
   11556             :                                  "[C]",
   11557           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnTConv,
   11558           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideTConvValue);
   11559           0 :                 SetupEMSActuator(state,
   11560             :                                  "Other Side Boundary Conditions",
   11561           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   11562             :                                  "Convection Heat Transfer Coefficient",
   11563             :                                  "[W/m2-K]",
   11564           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnHConv,
   11565           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideHConvValue);
   11566           0 :                 SetupEMSActuator(state,
   11567             :                                  "Other Side Boundary Conditions",
   11568           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   11569             :                                  "Radiation Effective Temperature",
   11570             :                                  "[C]",
   11571           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnTRad,
   11572           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideTRadValue);
   11573           0 :                 SetupEMSActuator(state,
   11574             :                                  "Other Side Boundary Conditions",
   11575           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   11576             :                                  "Radiation Linear Heat Transfer Coefficient",
   11577             :                                  "[W/m2-K]",
   11578           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnHrad,
   11579           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideHradValue);
   11580             :             }
   11581             :         }
   11582             : 
   11583         791 :         for (Loop = 1; Loop <= state.dataSurface->TotOSCM; ++Loop) {
   11584          20 :             if (Loop == 1) {
   11585             :                 static constexpr std::string_view OSCMFormat1("! <Other Side Conditions Model>,Name,Class\n");
   11586          11 :                 print(state.files.eio, OSCMFormat1);
   11587             :             }
   11588          20 :             print(state.files.eio, "Other Side Conditions Model,{},{}\n", state.dataSurface->OSCM(Loop).Name, state.dataSurface->OSCM(Loop).Class);
   11589             :         }
   11590         771 :     }
   11591             : 
   11592         771 :     void GetMovableInsulationData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
   11593             :     {
   11594             : 
   11595             :         // SUBROUTINE INFORMATION:
   11596             :         //       AUTHOR         Linda Lawrie
   11597             :         //       DATE WRITTEN   May 2000
   11598             :         //       MODIFIED       na
   11599             :         //       RE-ENGINEERED  na
   11600             : 
   11601             :         // PURPOSE OF THIS SUBROUTINE:
   11602             :         // This subroutine gets the movable insulation data that can be associated with
   11603             :         // a surface.
   11604             : 
   11605             :         // METHODOLOGY EMPLOYED:
   11606             :         // na
   11607             : 
   11608             :         // REFERENCES:
   11609             :         // Movable Insulation Definition
   11610             :         // SurfaceControl:MovableInsulation,
   11611             :         //       \memo Exterior or Interior Insulation on opaque surfaces
   11612             :         //   A1, \field Insulation Type
   11613             :         //       \required-field
   11614             :         //       \type choice
   11615             :         //       \key Outside
   11616             :         //       \key Inside
   11617             :         //   A2, \field Surface Name
   11618             :         //       \required-field
   11619             :         //       \type object-list
   11620             :         //       \object-list SurfaceNames
   11621             :         //   A3, \field Material Name
   11622             :         //       \required-field
   11623             :         //       \object-list MaterialName
   11624             :         //   A4; \field Schedule Name
   11625             :         //        \required-field
   11626             :         //        \type object-list
   11627             :         //        \object-list ScheduleNames
   11628             : 
   11629             :         // Using/Aliasing
   11630             : 
   11631             :         using ScheduleManager::GetScheduleIndex;
   11632             : 
   11633             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11634             :         int NAlphas;
   11635             :         int NNums;
   11636             :         int IOStat;
   11637             :         int Loop;
   11638             :         int NMatInsul;
   11639             :         int SurfNum;
   11640             :         int MaterNum;
   11641             :         int SchNum;
   11642             : 
   11643             :         enum class InsulationType
   11644             :         {
   11645             :             Invalid = -1,
   11646             :             Outside,
   11647             :             Inside,
   11648             :             Num
   11649             :         };
   11650         771 :         constexpr std::array<std::string_view, static_cast<int>(InsulationType::Num)> insulationTypeNamesUC = {"OUTSIDE", "INSIDE"};
   11651             : 
   11652         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   11653         771 :         cCurrentModuleObject = "SurfaceControl:MovableInsulation";
   11654         771 :         NMatInsul = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11655         776 :         for (Loop = 1; Loop <= NMatInsul; ++Loop) {
   11656          35 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   11657             :                                                                      cCurrentModuleObject,
   11658             :                                                                      Loop,
   11659           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
   11660             :                                                                      NAlphas,
   11661           5 :                                                                      state.dataIPShortCut->rNumericArgs,
   11662             :                                                                      NNums,
   11663             :                                                                      IOStat,
   11664           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   11665           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   11666           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   11667           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   11668           5 :             SurfNum =
   11669           5 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
   11670           5 :             MaterNum =
   11671           5 :                 UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
   11672           5 :             SchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
   11673             :             InsulationType insulationType =
   11674           5 :                 static_cast<InsulationType>(getEnumerationValue(insulationTypeNamesUC, state.dataIPShortCut->cAlphaArgs(1)));
   11675           5 :             if (insulationType == InsulationType::Invalid) {
   11676           0 :                 ShowSevereError(state,
   11677           0 :                                 cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11678           0 :                                     state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
   11679           0 :                 ShowContinueError(state,
   11680           0 :                                   " invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
   11681             :                                       "\", [should be Inside or Outside]");
   11682           0 :                 ErrorsFound = true;
   11683             :             }
   11684           5 :             if (SurfNum == 0) {
   11685           0 :                 ShowSevereError(state,
   11686           0 :                                 cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11687           0 :                                     state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
   11688           0 :                 ShowContinueError(state, " invalid (not found) " + state.dataIPShortCut->cAlphaFieldNames(2));
   11689           0 :                 ErrorsFound = true;
   11690             :             } else {
   11691           5 :                 if (MaterNum == 0) {
   11692           0 :                     ShowSevereError(state,
   11693           0 :                                     cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11694           0 :                                         state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
   11695           0 :                     ShowContinueError(state,
   11696           0 :                                       " invalid (not found) " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" +
   11697           0 :                                           state.dataIPShortCut->cAlphaArgs(3) + "\"");
   11698           0 :                     ErrorsFound = true;
   11699             :                 } else {
   11700             : 
   11701             :                     Array1D_string const cMaterialGroupType({-1, 18},
   11702             :                                                             {"invalid",
   11703             :                                                              "Material/Material:NoMass",
   11704             :                                                              "Material:AirGap",
   11705             :                                                              "WindowMaterial:Shade",
   11706             :                                                              "WindowMaterial:Glazing*",
   11707             :                                                              "WindowMaterial:Gas",
   11708             :                                                              "WindowMaterial:Blind",
   11709             :                                                              "WindowMaterial:GasMixture",
   11710             :                                                              "WindowMaterial:Screen",
   11711             :                                                              "Material:RoofVegetation",
   11712             :                                                              "Material:InfraredTransparent",
   11713             :                                                              "WindowMaterial:SimpleGlazingSystem",
   11714             :                                                              "WindowMaterial:ComplexShade",
   11715             :                                                              "WindowMaterial:Gap",
   11716             :                                                              "WindowMaterial:Glazing:EquivalentLayer",
   11717             :                                                              "WindowMaterial:Shade:EquivalentLayer",
   11718             :                                                              "WindowMaterial:Drape:EquivalentLayer",
   11719             :                                                              "WindowMaterial:Blind:EquivalentLayer",
   11720             :                                                              "WindowMaterial:Screen:EquivalentLayer",
   11721          10 :                                                              "WindowMaterial:Gap:EquivalentLayer"});
   11722             : 
   11723           5 :                     DataHeatBalance::MaterialGroup const MaterialLayerGroup = state.dataMaterial->Material(MaterNum).Group;
   11724           5 :                     if (BITF_TEST_ANY(BITF(MaterialLayerGroup),
   11725             :                                       BITF(DataHeatBalance::MaterialGroup::WindowSimpleGlazing) |
   11726             :                                           BITF(DataHeatBalance::MaterialGroup::ShadeEquivalentLayer) |
   11727             :                                           BITF(DataHeatBalance::MaterialGroup::DrapeEquivalentLayer) |
   11728             :                                           BITF(DataHeatBalance::MaterialGroup::BlindEquivalentLayer) |
   11729             :                                           BITF(DataHeatBalance::MaterialGroup::ScreenEquivalentLayer) |
   11730             :                                           BITF(DataHeatBalance::MaterialGroup::GapEquivalentLayer))) {
   11731           0 :                         ShowSevereError(state, "Invalid movable insulation material for " + cCurrentModuleObject + ":");
   11732           0 :                         ShowSevereError(
   11733           0 :                             state, "...Movable insulation material type specified = " + cMaterialGroupType(static_cast<int>(MaterialLayerGroup)));
   11734           0 :                         ShowSevereError(state, "...Movable insulation material name specified = " + state.dataIPShortCut->cAlphaArgs(3));
   11735           0 :                         ErrorsFound = true;
   11736             :                     }
   11737           5 :                     if (SchNum == 0) {
   11738           0 :                         ShowSevereError(state,
   11739           0 :                                         cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11740           0 :                                             state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
   11741           0 :                         ShowContinueError(state,
   11742           0 :                                           " invalid (not found) " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" +
   11743           0 :                                               state.dataIPShortCut->cAlphaArgs(4) + "\"");
   11744           0 :                         ErrorsFound = true;
   11745             :                     } else {
   11746             :                         {
   11747           5 :                             switch (insulationType) {
   11748           2 :                             case InsulationType::Outside:
   11749           2 :                                 if (state.dataSurface->SurfMaterialMovInsulExt(SurfNum) > 0) {
   11750           0 :                                     ShowSevereError(state,
   11751           0 :                                                     cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11752           0 :                                                         state.dataIPShortCut->cAlphaArgs(2) + "\", already assigned.");
   11753           0 :                                     ShowContinueError(state,
   11754           0 :                                                       "\"Outside\", was already assigned Material=\"" +
   11755           0 :                                                           state.dataMaterial->Material(state.dataSurface->SurfMaterialMovInsulInt(SurfNum)).Name +
   11756             :                                                           "\".");
   11757           0 :                                     ShowContinueError(state,
   11758           0 :                                                       "attempting to assign Material=\"" + state.dataMaterial->Material(MaterNum).Name + "\".");
   11759           0 :                                     ErrorsFound = true;
   11760             :                                 }
   11761           2 :                                 state.dataSurface->SurfMaterialMovInsulExt(SurfNum) = MaterNum;
   11762           2 :                                 state.dataSurface->SurfSchedMovInsulExt(SurfNum) = SchNum;
   11763           2 :                                 state.dataSurface->AnyMovableInsulation = true;
   11764           2 :                                 if (state.dataMaterial->Material(MaterNum).Resistance <= 0.0) {
   11765           0 :                                     if (state.dataMaterial->Material(MaterNum).Conductivity <= 0.0 ||
   11766           0 :                                         state.dataMaterial->Material(MaterNum).Thickness <= 0.0) {
   11767           0 :                                         ShowSevereError(state,
   11768           0 :                                                         cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11769           0 :                                                             state.dataIPShortCut->cAlphaArgs(2) + "\", invalid material.");
   11770           0 :                                         ShowContinueError(state, "\"Outside\", invalid material for movable insulation.");
   11771           0 :                                         ShowContinueError(state,
   11772           0 :                                                           format("Material=\"{}\",Resistance=[{:.3R}], must be > 0 for use in Movable Insulation.",
   11773           0 :                                                                  state.dataMaterial->Material(MaterNum).Name,
   11774           0 :                                                                  state.dataMaterial->Material(MaterNum).Resistance));
   11775           0 :                                         ErrorsFound = true;
   11776           0 :                                     } else if (state.dataMaterial->Material(MaterNum).Conductivity > 0.0) {
   11777           0 :                                         state.dataMaterial->Material(MaterNum).Resistance =
   11778           0 :                                             state.dataMaterial->Material(MaterNum).Thickness / state.dataMaterial->Material(MaterNum).Conductivity;
   11779             :                                     }
   11780             :                                 }
   11781           2 :                                 if (state.dataMaterial->Material(MaterNum).Conductivity <= 0.0) {
   11782           1 :                                     if (state.dataMaterial->Material(MaterNum).Resistance <= 0.0) {
   11783           0 :                                         ShowSevereError(state,
   11784           0 :                                                         cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11785           0 :                                                             state.dataIPShortCut->cAlphaArgs(2) + "\", invalid material.");
   11786           0 :                                         ShowContinueError(state, "\"Outside\", invalid material for movable insulation.");
   11787           0 :                                         ShowContinueError(state,
   11788           0 :                                                           format("Material=\"{}\",Conductivity=[{:.3R}], must be > 0 for use in Movable Insulation.",
   11789           0 :                                                                  state.dataMaterial->Material(MaterNum).Name,
   11790           0 :                                                                  state.dataMaterial->Material(MaterNum).Conductivity));
   11791           0 :                                         ErrorsFound = true;
   11792             :                                     }
   11793             :                                 }
   11794           2 :                                 break;
   11795           3 :                             case InsulationType::Inside:
   11796           3 :                                 if (state.dataSurface->SurfMaterialMovInsulInt(SurfNum) > 0) {
   11797           0 :                                     ShowSevereError(state,
   11798           0 :                                                     cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11799           0 :                                                         state.dataIPShortCut->cAlphaArgs(2) + "\", already assigned.");
   11800           0 :                                     ShowContinueError(state,
   11801           0 :                                                       "\"Inside\", was already assigned Material=\"" +
   11802           0 :                                                           state.dataMaterial->Material(state.dataSurface->SurfMaterialMovInsulInt(SurfNum)).Name +
   11803             :                                                           "\".");
   11804           0 :                                     ShowContinueError(state,
   11805           0 :                                                       "attempting to assign Material=\"" + state.dataMaterial->Material(MaterNum).Name + "\".");
   11806           0 :                                     ErrorsFound = true;
   11807             :                                 }
   11808           3 :                                 state.dataSurface->SurfMaterialMovInsulInt(SurfNum) = MaterNum;
   11809           3 :                                 state.dataSurface->SurfSchedMovInsulInt(SurfNum) = SchNum;
   11810           3 :                                 state.dataSurface->AnyMovableInsulation = true;
   11811           3 :                                 if (state.dataMaterial->Material(MaterNum).Resistance <= 0.0) {
   11812           0 :                                     if (state.dataMaterial->Material(MaterNum).Conductivity <= 0.0 ||
   11813           0 :                                         state.dataMaterial->Material(MaterNum).Thickness <= 0.0) {
   11814           0 :                                         ShowSevereError(state,
   11815           0 :                                                         cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11816           0 :                                                             state.dataIPShortCut->cAlphaArgs(2) + "\", invalid material.");
   11817           0 :                                         ShowContinueError(state, "\"Inside\", invalid material for movable insulation.");
   11818           0 :                                         ShowContinueError(state,
   11819           0 :                                                           format("Material=\"{}\",Resistance=[{:.3R}], must be > 0 for use in Movable Insulation.",
   11820           0 :                                                                  state.dataMaterial->Material(MaterNum).Name,
   11821           0 :                                                                  state.dataMaterial->Material(MaterNum).Resistance));
   11822           0 :                                         ErrorsFound = true;
   11823           0 :                                     } else if (state.dataMaterial->Material(MaterNum).Conductivity > 0.0) {
   11824           0 :                                         state.dataMaterial->Material(MaterNum).Resistance =
   11825           0 :                                             state.dataMaterial->Material(MaterNum).Thickness / state.dataMaterial->Material(MaterNum).Conductivity;
   11826             :                                     }
   11827             :                                 }
   11828           3 :                                 break;
   11829           0 :                             default:
   11830           0 :                                 assert(false);
   11831             :                             }
   11832             :                         }
   11833           5 :                         if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
   11834           0 :                             ShowSevereError(state,
   11835           0 :                                             cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   11836           0 :                                                 state.dataIPShortCut->cAlphaArgs(2) + "\"");
   11837           0 :                             ShowContinueError(state, "invalid use on a Window. Use WindowShadingControl instead.");
   11838           0 :                             ErrorsFound = true;
   11839             :                         }
   11840             :                     }
   11841             :                 }
   11842             :             }
   11843             :         }
   11844         771 :     }
   11845             : 
   11846             :     // Calculates the volume (m3) of a zone using the surfaces as possible.
   11847         771 :     void CalculateZoneVolume(EnergyPlusData &state, const Array1D_bool &CeilingHeightEntered)
   11848             :     {
   11849             : 
   11850             :         // SUBROUTINE INFORMATION:
   11851             :         //       AUTHOR         Legacy Code
   11852             :         //       DATE WRITTEN   1992-1994
   11853             :         //       MODIFIED       Sep 2007, Mar 2017
   11854             : 
   11855             :         // METHODOLOGY EMPLOYED:
   11856             :         // Uses surface area information for calculations.  Modified to use the
   11857             :         // user-entered ceiling height (x floor area, if applicable) instead of using
   11858             :         // the calculated volume when the user enters the ceiling height.
   11859             : 
   11860             :         // REFERENCES:
   11861             :         // Legacy Code (IBLAST)
   11862             : 
   11863             :         using namespace Vectors;
   11864             : 
   11865             :         Real64 SumAreas;  // Sum of the Zone surface areas that are not "internal mass"
   11866             :         Real64 SurfCount; // Surface Count
   11867             :         int SurfNum;      // Loop counter for surfaces
   11868             :         int ZoneNum;      // Loop counter for Zones
   11869        1542 :         Array1D_int surfacenotused;
   11870             :         int notused;
   11871             :         int NFaces;
   11872             :         int NActFaces;
   11873             :         Real64 CalcVolume;
   11874             :         bool initmsg;
   11875             :         int iside;
   11876         771 :         auto &ShowZoneSurfaceHeaders = state.dataSurfaceGeometry->ShowZoneSurfaceHeaders;
   11877         771 :         auto &ErrCount5 = state.dataSurfaceGeometry->ErrCount5;
   11878             : 
   11879             :         // Object Data
   11880        1542 :         Polyhedron ZoneStruct;
   11881             : 
   11882         771 :         initmsg = true;
   11883         771 :         bool ShowZoneSurfaces = (state.dataInputProcessing->inputProcessor->getNumSectionsFound("SHOWZONESURFACES_DEBUG") > 0);
   11884             : 
   11885             :         enum class ZoneVolumeCalcMethod
   11886             :         {
   11887             :             Invalid = -1,
   11888             :             Enclosed,
   11889             :             FloorAreaTimesHeight1,
   11890             :             FloorAreaTimesHeight2,
   11891             :             CeilingAreaTimesHeight,
   11892             :             OpWallAreaTimesDistance,
   11893             :             UserProvided,
   11894             :             Num
   11895             :         };
   11896             : 
   11897         771 :         int countNotFullyEnclosedZones = 0;
   11898        5585 :         for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
   11899        4814 :             auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
   11900        4814 :             if (!state.dataHeatBal->Zone(ZoneNum).HasFloor) {
   11901           6 :                 ShowWarningError(state,
   11902           4 :                                  "No floor exists in Zone=\"" + state.dataHeatBal->Zone(ZoneNum).Name +
   11903             :                                      "\", zone floor area is zero. All values for this zone that are entered per floor area will be zero.");
   11904             :             }
   11905             : 
   11906        4814 :             SumAreas = 0.0;
   11907        4814 :             SurfCount = 0.0;
   11908             :             // Use AllSurfaceFirst which includes air boundaries
   11909        4814 :             NFaces = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast - state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst + 1;
   11910        4814 :             notused = 0;
   11911        4814 :             ZoneStruct.NumSurfaceFaces = NFaces;
   11912        4814 :             ZoneStruct.SurfaceFace.allocate(NFaces);
   11913        4814 :             NActFaces = 0;
   11914        4814 :             surfacenotused.dimension(NFaces, 0);
   11915             : 
   11916       47034 :             for (SurfNum = state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst; SurfNum <= state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast; ++SurfNum) {
   11917             : 
   11918             :                 // Only include Base Surfaces in Calc.
   11919             : 
   11920      113904 :                 if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall &&
   11921       56436 :                     state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor &&
   11922       14216 :                     state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof) {
   11923        8726 :                     ++notused;
   11924        8726 :                     surfacenotused(notused) = SurfNum;
   11925        8726 :                     continue;
   11926             :                 }
   11927             : 
   11928       33494 :                 ++NActFaces;
   11929       33494 :                 ZoneStruct.SurfaceFace(NActFaces).FacePoints.allocate(state.dataSurface->Surface(SurfNum).Sides);
   11930       33494 :                 ZoneStruct.SurfaceFace(NActFaces).NSides = state.dataSurface->Surface(SurfNum).Sides;
   11931       33494 :                 ZoneStruct.SurfaceFace(NActFaces).SurfNum = SurfNum;
   11932       33494 :                 ZoneStruct.SurfaceFace(NActFaces).FacePoints({1, state.dataSurface->Surface(SurfNum).Sides}) =
   11933       66988 :                     state.dataSurface->Surface(SurfNum).Vertex({1, state.dataSurface->Surface(SurfNum).Sides});
   11934       66988 :                 CreateNewellAreaVector(ZoneStruct.SurfaceFace(NActFaces).FacePoints,
   11935       33494 :                                        ZoneStruct.SurfaceFace(NActFaces).NSides,
   11936       33494 :                                        ZoneStruct.SurfaceFace(NActFaces).NewellAreaVector);
   11937       33494 :                 SumAreas += VecLength(ZoneStruct.SurfaceFace(NActFaces).NewellAreaVector);
   11938             :             }
   11939        4814 :             ZoneStruct.NumSurfaceFaces = NActFaces;
   11940        4814 :             SurfCount = double(NActFaces);
   11941             : 
   11942             :             bool isFloorHorizontal;
   11943             :             bool isCeilingHorizontal;
   11944             :             bool areWallsVertical;
   11945        4814 :             std::tie(isFloorHorizontal, isCeilingHorizontal, areWallsVertical) = areSurfaceHorizAndVert(state, ZoneStruct);
   11946             :             Real64 oppositeWallArea;
   11947             :             Real64 distanceBetweenOppositeWalls;
   11948             : 
   11949        4814 :             bool areWallsSameHeight = areWallHeightSame(state, ZoneStruct);
   11950             : 
   11951        9628 :             std::vector<EdgeOfSurf> listOfedgeNotUsedTwice;
   11952        4814 :             bool isZoneEnclosed = isEnclosedVolume(ZoneStruct, listOfedgeNotUsedTwice);
   11953             :             ZoneVolumeCalcMethod volCalcMethod;
   11954             : 
   11955        4814 :             if (isZoneEnclosed) {
   11956        4795 :                 CalcVolume = CalcPolyhedronVolume(state, ZoneStruct);
   11957        4795 :                 volCalcMethod = ZoneVolumeCalcMethod::Enclosed;
   11958          36 :             } else if (state.dataHeatBal->Zone(ZoneNum).FloorArea > 0.0 && state.dataHeatBal->Zone(ZoneNum).CeilingHeight > 0.0 &&
   11959          17 :                        areFloorAndCeilingSame(state, ZoneStruct)) {
   11960          13 :                 CalcVolume = state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
   11961          13 :                 volCalcMethod = ZoneVolumeCalcMethod::FloorAreaTimesHeight1;
   11962           7 :             } else if (isFloorHorizontal && areWallsVertical && areWallsSameHeight && state.dataHeatBal->Zone(ZoneNum).FloorArea > 0.0 &&
   11963           1 :                        state.dataHeatBal->Zone(ZoneNum).CeilingHeight > 0.0) {
   11964           1 :                 CalcVolume = state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
   11965           1 :                 volCalcMethod = ZoneVolumeCalcMethod::FloorAreaTimesHeight2;
   11966           5 :             } else if (isCeilingHorizontal && areWallsVertical && areWallsSameHeight && state.dataHeatBal->Zone(ZoneNum).CeilingArea > 0.0 &&
   11967           0 :                        state.dataHeatBal->Zone(ZoneNum).CeilingHeight > 0.0) {
   11968           0 :                 CalcVolume = state.dataHeatBal->Zone(ZoneNum).CeilingArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
   11969           0 :                 volCalcMethod = ZoneVolumeCalcMethod::CeilingAreaTimesHeight;
   11970           5 :             } else if (areOppositeWallsSame(state, ZoneStruct, oppositeWallArea, distanceBetweenOppositeWalls)) {
   11971           3 :                 CalcVolume = oppositeWallArea * distanceBetweenOppositeWalls;
   11972           3 :                 volCalcMethod = ZoneVolumeCalcMethod::OpWallAreaTimesDistance;
   11973           2 :             } else if (state.dataHeatBal->Zone(ZoneNum).Volume == DataGlobalConstants::AutoCalculate) { // no user entered zone volume
   11974           0 :                 ShowSevereError(state,
   11975           0 :                                 "For zone: " + state.dataHeatBal->Zone(ZoneNum).Name +
   11976             :                                     " it is not possible to calculate the volume from the surrounding surfaces so either provide the volume value or "
   11977             :                                     "define all the surfaces to fully enclose the zone.");
   11978           0 :                 CalcVolume = 0.;
   11979           0 :                 volCalcMethod = ZoneVolumeCalcMethod::Invalid;
   11980             :             } else {
   11981           2 :                 CalcVolume = 0.;
   11982           2 :                 volCalcMethod = ZoneVolumeCalcMethod::UserProvided;
   11983             :             }
   11984        4814 :             if (!isZoneEnclosed) {
   11985          19 :                 ++countNotFullyEnclosedZones;
   11986          19 :                 if (state.dataGlobal->DisplayExtraWarnings) { // report missing
   11987           0 :                     ShowWarningError(state,
   11988           0 :                                      "CalculateZoneVolume: The Zone=\"" + state.dataHeatBal->Zone(ZoneNum).Name +
   11989             :                                          "\" is not fully enclosed. To be fully enclosed, each edge of a surface must also be an edge on one "
   11990             :                                          "other surface.");
   11991           0 :                     switch (volCalcMethod) {
   11992           0 :                     case ZoneVolumeCalcMethod::FloorAreaTimesHeight1:
   11993           0 :                         ShowContinueError(state,
   11994             :                                           "  The zone volume was calculated using the floor area times ceiling height method where the floor and "
   11995             :                                           "ceiling are the same except for the z-coordinates.");
   11996           0 :                         break;
   11997           0 :                     case ZoneVolumeCalcMethod::FloorAreaTimesHeight2:
   11998           0 :                         ShowContinueError(state,
   11999             :                                           "  The zone volume was calculated using the floor area times ceiling height method where the floor is "
   12000             :                                           "horizontal, the walls are vertical, and the wall heights are all the same.");
   12001           0 :                         break;
   12002           0 :                     case ZoneVolumeCalcMethod::CeilingAreaTimesHeight:
   12003           0 :                         ShowContinueError(state,
   12004             :                                           "  The zone volume was calculated using the ceiling area times ceiling height method where the ceiling is "
   12005             :                                           "horizontal, the walls are vertical, and the wall heights are all the same.");
   12006           0 :                         break;
   12007           0 :                     case ZoneVolumeCalcMethod::OpWallAreaTimesDistance:
   12008           0 :                         ShowContinueError(state,
   12009             :                                           "  The zone volume was calculated using the opposite wall area times the distance between them method ");
   12010           0 :                         break;
   12011           0 :                     case ZoneVolumeCalcMethod::UserProvided:
   12012           0 :                         ShowContinueError(state, "  The zone volume was provided as an input to the ZONE object ");
   12013           0 :                         break;
   12014           0 :                     case ZoneVolumeCalcMethod::Invalid:
   12015           0 :                         ShowContinueError(state, "  The zone volume was not calculated and an error exists. ");
   12016           0 :                         break;
   12017           0 :                     case ZoneVolumeCalcMethod::Enclosed: // should not be called but completes enumeration
   12018           0 :                         ShowContinueError(state, "  The zone volume was calculated using multiple pyramids and was fully enclosed. ");
   12019           0 :                         break;
   12020           0 :                     default:
   12021           0 :                         assert(false);
   12022             :                     }
   12023           0 :                     for (auto &edge : listOfedgeNotUsedTwice) {
   12024           0 :                         if (edge.count < 2) {
   12025           0 :                             ShowContinueError(
   12026             :                                 state,
   12027           0 :                                 fmt::format("  The surface \"{}\" has an edge that was used only once: it is not an edge on another surface",
   12028           0 :                                             state.dataSurface->Surface(edge.surfNum).Name));
   12029             : 
   12030             :                         } else {
   12031           0 :                             ShowContinueError(
   12032             :                                 state,
   12033           0 :                                 fmt::format("  The surface \"{}\" has an edge that was used {} times: it is an edge on three or more surfaces: ",
   12034           0 :                                             state.dataSurface->Surface(edge.surfNum).Name,
   12035             :                                             edge.count));
   12036           0 :                             std::string surfaceNames = "    It was found on the following Surfaces: ";
   12037           0 :                             for (int surfNum : edge.otherSurfNums) {
   12038           0 :                                 surfaceNames += fmt::format("'{}' ", state.dataSurface->Surface(surfNum).Name);
   12039             :                             }
   12040           0 :                             ShowContinueError(state, surfaceNames);
   12041             :                         }
   12042           0 :                         ShowContinueError(state, format("    Vertex start {{ {:.4R}, {:.4R}, {:.4R}}}", edge.start.x, edge.start.y, edge.start.z));
   12043           0 :                         ShowContinueError(state, format("    Vertex end   {{ {:.4R}, {:.4R}, {:.4R}}}", edge.end.x, edge.end.y, edge.end.z));
   12044             :                     }
   12045             :                 }
   12046             :             }
   12047        4814 :             if (state.dataHeatBal->Zone(ZoneNum).Volume > 0.0) { // User entered zone volume, produce message if not near calculated
   12048        2288 :                 if (CalcVolume > 0.0) {
   12049        2286 :                     if (std::abs(CalcVolume - state.dataHeatBal->Zone(ZoneNum).Volume) / state.dataHeatBal->Zone(ZoneNum).Volume > 0.05) {
   12050           2 :                         ++ErrCount5;
   12051           2 :                         if (ErrCount5 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
   12052           1 :                             if (initmsg) {
   12053           1 :                                 ShowMessage(state,
   12054             :                                             "Note that the following warning(s) may/will occur if you have not enclosed your zone completely.");
   12055           1 :                                 initmsg = false;
   12056             :                             }
   12057           1 :                             ShowWarningError(state, "Entered Zone Volumes differ from calculated zone volume(s).");
   12058           1 :                             ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
   12059             :                         }
   12060           2 :                         if (state.dataGlobal->DisplayExtraWarnings) {
   12061           0 :                             if (initmsg) {
   12062           0 :                                 ShowMessage(state,
   12063             :                                             "Note that the following warning(s) may/will occur if you have not enclosed your zone completely.");
   12064           0 :                                 initmsg = false;
   12065             :                             }
   12066             :                             // Warn user of using specified Zone Volume
   12067           0 :                             ShowWarningError(state,
   12068           0 :                                              "Entered Volume entered for Zone=\"" + state.dataHeatBal->Zone(ZoneNum).Name +
   12069             :                                                  "\" significantly different from calculated Volume");
   12070           0 :                             ShowContinueError(state,
   12071           0 :                                               format("Entered Zone Volume value={:.2R}, Calculated Zone Volume value={:.2R}, entered volume will be "
   12072             :                                                      "used in calculations.",
   12073           0 :                                                      state.dataHeatBal->Zone(ZoneNum).Volume,
   12074           0 :                                                      CalcVolume));
   12075             :                         }
   12076             :                     }
   12077             :                 }
   12078        2526 :             } else if (CeilingHeightEntered(ZoneNum)) { // User did not enter zone volume, but entered ceiling height
   12079         123 :                 if (state.dataHeatBal->Zone(ZoneNum).FloorArea > 0.0) {
   12080         123 :                     state.dataHeatBal->Zone(ZoneNum).Volume =
   12081         123 :                         state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
   12082             :                 } else { // ceiling height entered but floor area zero
   12083           0 :                     state.dataHeatBal->Zone(ZoneNum).Volume = CalcVolume;
   12084             :                 }
   12085             :             } else { // Neither ceiling height nor volume entered
   12086        2403 :                 state.dataHeatBal->Zone(ZoneNum).Volume = CalcVolume;
   12087             :             }
   12088             : 
   12089        4814 :             if (state.dataHeatBal->Zone(ZoneNum).Volume <= 0.0) {
   12090           0 :                 ShowWarningError(state, "Indicated Zone Volume <= 0.0 for Zone=" + state.dataHeatBal->Zone(ZoneNum).Name);
   12091           0 :                 ShowContinueError(state, format("The calculated Zone Volume was={:.2R}", state.dataHeatBal->Zone(ZoneNum).Volume));
   12092           0 :                 ShowContinueError(state, "The simulation will continue with the Zone Volume set to 10.0 m3. ");
   12093           0 :                 ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
   12094           0 :                 state.dataHeatBal->Zone(ZoneNum).Volume = 10.;
   12095             :             }
   12096             :             // For now - pro-rate space volumes by floor area, if not entered
   12097        9632 :             for (int spaceNum : thisZone.spaceIndexes) {
   12098        4818 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
   12099             :                 // don't touch if already user-specified
   12100        4818 :                 if (thisSpace.Volume > 0.0) continue;
   12101        4818 :                 if (thisZone.numSpaces == 1) {
   12102        4812 :                     thisSpace.Volume = thisZone.Volume;
   12103           6 :                 } else if (thisZone.FloorArea > 0.0) {
   12104           6 :                     thisSpace.Volume = thisZone.Volume * thisSpace.floorArea / thisZone.FloorArea;
   12105             :                 }
   12106             :             }
   12107        4814 :             Real64 totSpacesVolume = 0.0;
   12108        9632 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
   12109        4818 :                 totSpacesVolume += state.dataHeatBal->space(spaceNum).Volume;
   12110             :             }
   12111        4814 :             if (totSpacesVolume > 0.0) {
   12112        9632 :                 for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
   12113        4818 :                     state.dataHeatBal->space(spaceNum).fracZoneVolume = state.dataHeatBal->space(spaceNum).Volume / totSpacesVolume;
   12114             :                 }
   12115             :             } // else leave fractions at zero
   12116             : 
   12117        4814 :             if (ShowZoneSurfaces) {
   12118           0 :                 if (ShowZoneSurfaceHeaders) {
   12119           0 :                     print(state.files.debug, "{}\n", "===================================");
   12120           0 :                     print(state.files.debug, "{}\n", "showing zone surfaces used and not used in volume calculation");
   12121           0 :                     print(state.files.debug, "{}\n", "for volume calculation, only floors, walls and roofs/ceilings are used");
   12122           0 :                     print(state.files.debug, "{}\n", "surface class, 1=wall, 2=floor, 3=roof/ceiling");
   12123           0 :                     print(state.files.debug, "{}\n", "unused surface class(es), 5=internal mass, 11=window, 12=glass door");
   12124           0 :                     print(state.files.debug, "{}\n", "                          13=door, 14=shading, 15=overhang, 16=fin");
   12125           0 :                     print(state.files.debug, "{}\n", "                          17=TDD Dome, 18=TDD Diffuser");
   12126           0 :                     ShowZoneSurfaceHeaders = false;
   12127             :                 }
   12128           0 :                 print(state.files.debug, "{}\n", "===================================");
   12129           0 :                 print(state.files.debug, "zone={} calc volume={}\n", state.dataHeatBal->Zone(ZoneNum).Name, CalcVolume);
   12130           0 :                 print(state.files.debug, " nsurfaces={} nactual={}\n", NFaces, NActFaces);
   12131             :             }
   12132       38308 :             for (SurfNum = 1; SurfNum <= ZoneStruct.NumSurfaceFaces; ++SurfNum) {
   12133       33494 :                 if (ShowZoneSurfaces) {
   12134           0 :                     if (SurfNum <= NActFaces) {
   12135           0 :                         print(state.files.debug,
   12136             :                               "surface={} nsides={}\n",
   12137           0 :                               ZoneStruct.SurfaceFace(SurfNum).SurfNum,
   12138           0 :                               ZoneStruct.SurfaceFace(SurfNum).NSides);
   12139           0 :                         print(state.files.debug,
   12140             :                               "surface name={} class={}\n",
   12141           0 :                               state.dataSurface->Surface(ZoneStruct.SurfaceFace(SurfNum).SurfNum).Name,
   12142           0 :                               state.dataSurface->Surface(ZoneStruct.SurfaceFace(SurfNum).SurfNum).Class);
   12143           0 :                         print(state.files.debug, "area={}\n", state.dataSurface->Surface(ZoneStruct.SurfaceFace(SurfNum).SurfNum).GrossArea);
   12144           0 :                         for (iside = 1; iside <= ZoneStruct.SurfaceFace(SurfNum).NSides; ++iside) {
   12145           0 :                             auto const &FacePoint(ZoneStruct.SurfaceFace(SurfNum).FacePoints(iside));
   12146           0 :                             print(state.files.debug, "{} {} {}\n", FacePoint.x, FacePoint.y, FacePoint.z);
   12147             :                         }
   12148             :                     }
   12149             :                 }
   12150       33494 :                 ZoneStruct.SurfaceFace(SurfNum).FacePoints.deallocate();
   12151             :             }
   12152        4814 :             if (ShowZoneSurfaces) {
   12153           0 :                 for (SurfNum = 1; SurfNum <= notused; ++SurfNum) {
   12154           0 :                     print(state.files.debug,
   12155             :                           "notused:surface={} name={} class={}\n",
   12156             :                           surfacenotused(SurfNum),
   12157           0 :                           state.dataSurface->Surface(surfacenotused(SurfNum)).Name,
   12158           0 :                           state.dataSurface->Surface(surfacenotused(SurfNum)).Class);
   12159             :                 }
   12160             :             }
   12161             : 
   12162        4814 :             ZoneStruct.SurfaceFace.deallocate();
   12163        4814 :             surfacenotused.deallocate();
   12164             : 
   12165             :         } // zone loop
   12166         771 :         if (!state.dataGlobal->DisplayExtraWarnings) {
   12167         723 :             if (countNotFullyEnclosedZones == 1) {
   12168          11 :                 ShowWarningError(
   12169             :                     state, "CalculateZoneVolume: 1 zone is not fully enclosed. For more details use:  Output:Diagnostics,DisplayExtrawarnings; ");
   12170         712 :             } else if (countNotFullyEnclosedZones > 1) {
   12171          12 :                 ShowWarningError(state,
   12172           8 :                                  format("CalculateZoneVolume: {} zones are not fully enclosed. For more details use:  "
   12173             :                                         "Output:Diagnostics,DisplayExtrawarnings; ",
   12174           4 :                                         countNotFullyEnclosedZones));
   12175             :             }
   12176             :         }
   12177         771 :     }
   12178             : 
   12179             :     // test if the volume described by the polyhedron if full enclosed (would not leak)
   12180        4814 :     bool isEnclosedVolume(DataVectorTypes::Polyhedron const &zonePoly, std::vector<EdgeOfSurf> &edgeNot2)
   12181             :     {
   12182             :         // J. Glazer - March 2017
   12183             : 
   12184        9628 :         std::vector<Vector> uniqueVertices = makeListOfUniqueVertices(zonePoly);
   12185             : 
   12186        9628 :         std::vector<EdgeOfSurf> edgeNot2orig = edgesNotTwoForEnclosedVolumeTest(zonePoly, uniqueVertices);
   12187             :         // if all edges had two counts then it is fully enclosed
   12188        4814 :         if (edgeNot2orig.empty()) {
   12189        3848 :             edgeNot2 = edgeNot2orig;
   12190        3848 :             return true;
   12191             :         } else { // if the count is three or greater it is likely that a vertex that is colinear was counted on the faces on one edge and not
   12192             :                  // on the "other side" of the edge Go through all the points looking for the number that are colinear and see if that is
   12193             :                  // consistent with the number of edges found that didn't have a count of two
   12194             :             DataVectorTypes::Polyhedron updatedZonePoly = updateZonePolygonsForMissingColinearPoints(
   12195        1932 :                 zonePoly, uniqueVertices); // this is done after initial test since it is computationally intensive.
   12196        1932 :             std::vector<EdgeOfSurf> edgeNot2again = edgesNotTwoForEnclosedVolumeTest(updatedZonePoly, uniqueVertices);
   12197         966 :             if (edgeNot2again.empty()) {
   12198         947 :                 return true;
   12199             :             } else {
   12200          19 :                 edgeNot2 = edgesInBoth(edgeNot2orig,
   12201             :                                        edgeNot2again); // only return a list of those edges that appear in both the original edge and the
   12202             :                                                        // revised edges this eliminates added edges that will confuse users and edges that
   12203             :                                                        // were caught by the updateZonePoly routine
   12204          19 :                 return false;
   12205             :             }
   12206             :         }
   12207             :     }
   12208             : 
   12209             :     // returns a vector of edges that are in both vectors
   12210          19 :     std::vector<EdgeOfSurf> edgesInBoth(std::vector<EdgeOfSurf> edges1, std::vector<EdgeOfSurf> edges2)
   12211             :     {
   12212             :         // J. Glazer - June 2017
   12213             :         // this is not optimized but the number of edges for a typical polyhedron is 12 and is probably rarely bigger than 20.
   12214             : 
   12215          19 :         std::vector<EdgeOfSurf> inBoth;
   12216         251 :         for (const auto &e1 : edges1) {
   12217        3107 :             for (const auto &e2 : edges2) {
   12218        3063 :                 if (edgesEqualOnSameSurface(e1, e2)) {
   12219         188 :                     inBoth.push_back(e1);
   12220         188 :                     break;
   12221             :                 }
   12222             :             }
   12223             :         }
   12224          19 :         return inBoth;
   12225             :     }
   12226             : 
   12227             :     // returns true if the edges match - including the surface number
   12228        3063 :     bool edgesEqualOnSameSurface(EdgeOfSurf a, EdgeOfSurf b)
   12229             :     {
   12230        3063 :         if (a.surfNum != b.surfNum) {
   12231        2619 :             return false;
   12232             :         }
   12233             : 
   12234             :         // vertex comparison (we compare indices, so absolute equal)
   12235         444 :         return ((a.start == b.start && a.end == b.end) || (a.start == b.end && a.end == b.start));
   12236             :     }
   12237             : 
   12238             :     // returns the number of times the edges of the polyhedron of the zone are not used twice by the sides
   12239        5780 :     std::vector<EdgeOfSurf> edgesNotTwoForEnclosedVolumeTest(DataVectorTypes::Polyhedron const &zonePoly, std::vector<Vector> const &uniqueVertices)
   12240             :     {
   12241             :         // J. Glazer - March 2017
   12242             : 
   12243             :         using DataVectorTypes::Vector;
   12244             : 
   12245      271317 :         struct EdgeByPts
   12246             :         {
   12247             :             int start;
   12248             :             int end;
   12249             :             int count;
   12250             :             int firstSurfNum;
   12251             :             std::vector<int> otherSurfNums;
   12252       90439 :             EdgeByPts() : start(0), end(0), count(0), firstSurfNum(0)
   12253             :             {
   12254       90439 :             }
   12255             :         };
   12256       11560 :         std::vector<EdgeByPts> uniqueEdges;
   12257        5780 :         uniqueEdges.reserve(zonePoly.NumSurfaceFaces * 6);
   12258             : 
   12259             :         // construct list of unique edges
   12260       11560 :         Vector curVertex;
   12261             :         int curVertexIndex;
   12262       47553 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12263       83546 :             Vector prevVertex;
   12264             :             int prevVertexIndex;
   12265      213580 :             for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12266      171807 :                 if (jVertex == 1) {
   12267       41773 :                     prevVertex = zonePoly.SurfaceFace(iFace).FacePoints(zonePoly.SurfaceFace(iFace).NSides); // the last point
   12268       41773 :                     prevVertexIndex = findIndexOfVertex(prevVertex, uniqueVertices);
   12269             :                 } else {
   12270      130034 :                     prevVertex = curVertex;
   12271      130034 :                     prevVertexIndex = curVertexIndex;
   12272             :                 }
   12273      171807 :                 curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12274      171807 :                 curVertexIndex = findIndexOfVertex(curVertex, uniqueVertices); // uses isAlmostEqual3dPt
   12275     5237228 :                 auto it = std::find_if(uniqueEdges.begin(), uniqueEdges.end(), [&curVertexIndex, &prevVertexIndex](const auto &edge) {
   12276     4897511 :                     return ((edge.start == curVertexIndex && edge.end == prevVertexIndex) ||
   12277     3151500 :                             (edge.start == prevVertexIndex && edge.end == curVertexIndex));
   12278     2094730 :                 });
   12279      171807 :                 if (it == uniqueEdges.end()) {
   12280      180878 :                     EdgeByPts curEdge;
   12281       90439 :                     curEdge.start = prevVertexIndex;
   12282       90439 :                     curEdge.end = curVertexIndex;
   12283       90439 :                     curEdge.count = 1;
   12284       90439 :                     curEdge.firstSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12285       90439 :                     uniqueEdges.emplace_back(curEdge);
   12286             :                 } else {
   12287       81368 :                     ++(it->count);
   12288       81368 :                     it->otherSurfNums.push_back(zonePoly.SurfaceFace(iFace).SurfNum);
   12289             :                 }
   12290             :             }
   12291             :         }
   12292             :         // All edges for an enclosed polyhedron should be shared by two (and only two) sides.
   12293             :         // So if the count is not two for all edges, the polyhedron is not enclosed
   12294        5780 :         std::vector<EdgeOfSurf> edgesNotTwoCount;
   12295       96219 :         for (const auto &anEdge : uniqueEdges) {
   12296       90439 :             if (anEdge.count != 2) {
   12297       18414 :                 EdgeOfSurf curEdgeOne;
   12298        9207 :                 curEdgeOne.surfNum = anEdge.firstSurfNum;
   12299        9207 :                 curEdgeOne.start = uniqueVertices[anEdge.start];
   12300        9207 :                 curEdgeOne.end = uniqueVertices[anEdge.end];
   12301        9207 :                 curEdgeOne.count = anEdge.count;
   12302        9207 :                 curEdgeOne.otherSurfNums = anEdge.otherSurfNums;
   12303        9207 :                 edgesNotTwoCount.push_back(curEdgeOne);
   12304             :             }
   12305             :         }
   12306       11560 :         return edgesNotTwoCount;
   12307             :     }
   12308             : 
   12309             :     // create a list of unique vertices given the polyhedron describing the zone
   12310        4814 :     std::vector<Vector> makeListOfUniqueVertices(DataVectorTypes::Polyhedron const &zonePoly)
   12311             :     {
   12312             :         // J. Glazer - March 2017
   12313             : 
   12314             :         using DataVectorTypes::Vector;
   12315        4814 :         std::vector<Vector> uniqVertices;
   12316        4814 :         uniqVertices.reserve(zonePoly.NumSurfaceFaces * 6);
   12317             : 
   12318       38308 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12319      168189 :             for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12320      269390 :                 Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12321      134695 :                 if (uniqVertices.size() == 0) {
   12322        4814 :                     uniqVertices.emplace_back(curVertex);
   12323             :                 } else {
   12324      129881 :                     bool found = false;
   12325      781357 :                     for (const auto &unqV : uniqVertices) {
   12326      740748 :                         if (isAlmostEqual3dPt(curVertex, unqV)) {
   12327       89272 :                             found = true;
   12328       89272 :                             break;
   12329             :                         }
   12330             :                     }
   12331      129881 :                     if (!found) {
   12332       40609 :                         uniqVertices.emplace_back(curVertex);
   12333             :                     }
   12334             :                 }
   12335             :             }
   12336             :         }
   12337        4814 :         return uniqVertices;
   12338             :     }
   12339             : 
   12340             :     // updates the polyhedron used to describe a zone to include points on an edge that are between and collinear to points already describing
   12341             :     // the edge
   12342         966 :     DataVectorTypes::Polyhedron updateZonePolygonsForMissingColinearPoints(DataVectorTypes::Polyhedron const &zonePoly,
   12343             :                                                                            std::vector<Vector> const &uniqVertices)
   12344             :     {
   12345             :         // J. Glazer - March 2017
   12346             : 
   12347             :         using DataVectorTypes::Vector;
   12348             : 
   12349         966 :         DataVectorTypes::Polyhedron updZonePoly = zonePoly; // set the return value to the original polyhedron describing the zone
   12350             : 
   12351       10731 :         for (auto &updFace : updZonePoly.SurfaceFace) {
   12352        9765 :             bool insertedVertext = true;
   12353       36725 :             while (insertedVertext) {
   12354       13480 :                 insertedVertext = false;
   12355       13480 :                 auto &vertices = updFace.FacePoints;
   12356       60525 :                 for (auto it = vertices.begin(); it != vertices.end(); ++it) {
   12357             : 
   12358       50760 :                     auto itnext = std::next(it);
   12359       50760 :                     if (itnext == std::end(vertices)) {
   12360        9531 :                         itnext = std::begin(vertices);
   12361             :                     }
   12362             : 
   12363       97805 :                     auto curVertex = *it;
   12364       97805 :                     auto nextVertex = *itnext;
   12365             : 
   12366             :                     // now go through all the vertices and see if they are colinear with start and end vertices
   12367      901865 :                     for (const auto &testVertex : uniqVertices) {
   12368      854820 :                         if (!isAlmostEqual3dPt(curVertex, testVertex) && !isAlmostEqual3dPt(nextVertex, testVertex)) {
   12369      755256 :                             if (isPointOnLineBetweenPoints(curVertex, nextVertex, testVertex)) {
   12370        3715 :                                 vertices.insert(itnext, testVertex);
   12371        3715 :                                 ++updFace.NSides;
   12372        3715 :                                 insertedVertext = true;
   12373        3715 :                                 break;
   12374             :                             }
   12375             :                         }
   12376             :                     }
   12377             :                     // Break out of the loop on vertices of the surface too, and start again at the while
   12378       50760 :                     if (insertedVertext) {
   12379        3715 :                         break;
   12380             :                     }
   12381             :                 }
   12382             :             }
   12383             :         }
   12384         966 :         return updZonePoly;
   12385             :     }
   12386             : 
   12387             :     // test if the ceiling and floor are the same except for their height difference by looking at the corners
   12388          17 :     bool areFloorAndCeilingSame(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
   12389             :     {
   12390             :         // J. Glazer - March 2017
   12391             : 
   12392             :         // check if the floor and ceiling are the same
   12393             :         // this is almost equivalent to saying, if you ignore the z-coordinate, are the vertices the same
   12394             :         // so if you could all the unique vertices of the floor and ceiling, ignoring the z-coordinate, they
   12395             :         // should always be even (they would be two but you might define multiple surfaces that meet in a corner)
   12396             : 
   12397             :         using DataVectorTypes::Vector;
   12398             :         using DataVectorTypes::Vector2dCount;
   12399             :         using DataVectorTypes::Vector_2d;
   12400             : 
   12401          34 :         std::vector<Vector2dCount> floorCeilingXY;
   12402          17 :         floorCeilingXY.reserve(zonePoly.NumSurfaceFaces * 6);
   12403             : 
   12404             :         // make list of x and y coordinates for all faces that are on the floor or ceiling
   12405         183 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12406         166 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12407         304 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Floor ||
   12408         138 :                 state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Roof) {
   12409         291 :                 for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12410         468 :                     Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12411         468 :                     Vector2dCount curXYc;
   12412         234 :                     curXYc.x = curVertex.x;
   12413         234 :                     curXYc.y = curVertex.y;
   12414         234 :                     curXYc.count = 1;
   12415         234 :                     bool found = false;
   12416         900 :                     for (Vector2dCount &curFloorCeiling : floorCeilingXY) { // can't use just "auto" because updating floorCeilingXY
   12417         790 :                         if (isAlmostEqual2dPt(curXYc, curFloorCeiling)) {   // count ignored in comparison
   12418         124 :                             ++curFloorCeiling.count;
   12419         124 :                             found = true;
   12420         124 :                             break;
   12421             :                         }
   12422             :                     }
   12423         234 :                     if (!found) {
   12424         110 :                         floorCeilingXY.emplace_back(curXYc);
   12425             :                     }
   12426             :                 }
   12427             :             }
   12428             :         }
   12429             :         // now make sure every point has been counted and even number of times (usually twice)
   12430             :         // if they are then the ceiling and floor are (almost certainly) the same x and y coordinates.
   12431          17 :         bool areFlrAndClgSame = true;
   12432          17 :         if (floorCeilingXY.size() > 0) {
   12433          91 :             for (auto curFloorCeiling : floorCeilingXY) {
   12434          78 :                 if (curFloorCeiling.count % 2 != 0) {
   12435           4 :                     areFlrAndClgSame = false;
   12436           4 :                     break;
   12437             :                 }
   12438             :             }
   12439             :         } else {
   12440           0 :             areFlrAndClgSame = false;
   12441             :         }
   12442          34 :         return areFlrAndClgSame;
   12443             :     }
   12444             : 
   12445             :     // test if the walls of a zone are all the same height using the polyhedron describing the zone geometry
   12446        4814 :     bool areWallHeightSame(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
   12447             :     {
   12448             :         // J. Glazer - March 2017
   12449             : 
   12450             :         // test if all the wall heights are the same (all walls have the same maximum z-coordinate
   12451             : 
   12452        4814 :         bool areWlHgtSame = true;
   12453        4814 :         Real64 wallHeightZ = -1.0E50;
   12454        4814 :         bool foundWallHeight = false;
   12455       37462 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12456       32718 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12457       32718 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
   12458       20999 :                 Real64 maxZ = -1.0E50;
   12459      104926 :                 for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12460      167854 :                     Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12461       83927 :                     if (maxZ < curVertex.z) {
   12462       21044 :                         maxZ = curVertex.z;
   12463             :                     }
   12464             :                 }
   12465       20999 :                 if (foundWallHeight) {
   12466       16207 :                     if (std::abs(maxZ - wallHeightZ) > 0.0254) { //  2.54 cm = 1 inch
   12467          70 :                         areWlHgtSame = false;
   12468          70 :                         break;
   12469             :                     }
   12470             :                 } else {
   12471        4792 :                     wallHeightZ = maxZ;
   12472        4792 :                     foundWallHeight = true;
   12473             :                 }
   12474             :             }
   12475             :         }
   12476        4814 :         return areWlHgtSame;
   12477             :     }
   12478             : 
   12479             :     // tests if the floor is horizontal, ceiling is horizontal, and walls are vertical and returns all three as a tuple of booleans
   12480        4814 :     std::tuple<bool, bool, bool> areSurfaceHorizAndVert(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
   12481             :     {
   12482             :         // J. Glazer - March 2017
   12483             : 
   12484             :         // check if floors and ceilings are horizontal and walls are vertical
   12485        4814 :         bool isFlrHoriz = true;
   12486        4814 :         bool isClgHoriz = true;
   12487        4814 :         bool areWlVert = true;
   12488       38308 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12489       33494 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12490       33494 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Floor) {
   12491        6522 :                 if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt - 180.) > 1.) { // with 1 degree angle
   12492           0 :                     isFlrHoriz = false;
   12493             :                 }
   12494       26972 :             } else if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Roof) { // includes ceilings
   12495        5490 :                 if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt) > 1.) {            // with 1 degree angle of
   12496         250 :                     isClgHoriz = false;
   12497             :                 }
   12498       21482 :             } else if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
   12499       21482 :                 if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt - 90) > 1.) { // with 1 degree angle
   12500           2 :                     areWlVert = false;
   12501             :                 }
   12502             :             }
   12503             :         }
   12504        4814 :         return std::make_tuple(isFlrHoriz, isClgHoriz, areWlVert);
   12505             :     }
   12506             : 
   12507             :     // tests whether a pair of walls in the zone are the same except offset from one another and facing the opposite direction and also
   12508             :     // returns the wall area and distance between
   12509           5 :     bool areOppositeWallsSame(EnergyPlusData &state,
   12510             :                               DataVectorTypes::Polyhedron const &zonePoly,
   12511             :                               Real64 &oppositeWallArea,            // return the area of the wall that has an opposite wall
   12512             :                               Real64 &distanceBetweenOppositeWalls // returns distance
   12513             :     )
   12514             :     {
   12515             :         // J. Glazer - March 2017
   12516             : 
   12517             :         // approach: if opposite surfaces have opposite azimuth and same area, then check the distance between the
   12518             :         // vertices( one counting backwards ) and if it is the same distance than assume that it is the same.
   12519             :         using DataVectorTypes::Vector;
   12520           5 :         bool foundOppEqual = false;
   12521          15 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12522          13 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12523          13 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
   12524          23 :                 std::vector<int> facesAtAz = listOfFacesFacingAzimuth(state, zonePoly, state.dataSurface->Surface(curSurfNum).Azimuth);
   12525          13 :                 bool allFacesEquidistant = true;
   12526          13 :                 oppositeWallArea = 0.;
   12527          28 :                 for (auto curFace : facesAtAz) {
   12528          25 :                     int possOppFace = findPossibleOppositeFace(state, zonePoly, curFace);
   12529          25 :                     if (possOppFace > 0) { // an opposite fact was found
   12530          16 :                         oppositeWallArea += state.dataSurface->Surface(zonePoly.SurfaceFace(curFace).SurfNum).Area;
   12531          16 :                         if (!areCornersEquidistant(zonePoly, curFace, possOppFace, distanceBetweenOppositeWalls)) {
   12532           1 :                             allFacesEquidistant = false;
   12533           1 :                             break;
   12534             :                         }
   12535             :                     } else {
   12536           9 :                         allFacesEquidistant = false;
   12537           9 :                         break;
   12538             :                     }
   12539             :                 }
   12540          13 :                 if (allFacesEquidistant) {
   12541           3 :                     foundOppEqual = true;
   12542           3 :                     break; // only need to find the first case where opposite walls are the same
   12543             :                 }
   12544             :             }
   12545             :         }
   12546           5 :         return foundOppEqual;
   12547             :     }
   12548             : 
   12549             :     // provides a list of indices of polyhedron faces that are facing a specific azimuth
   12550          13 :     std::vector<int> listOfFacesFacingAzimuth(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly, Real64 const azimuth)
   12551             :     {
   12552             :         // J. Glazer - March 2017
   12553             : 
   12554          13 :         std::vector<int> facingAzimuth;
   12555          13 :         facingAzimuth.reserve(zonePoly.NumSurfaceFaces);
   12556             : 
   12557         139 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12558         126 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12559         126 :             if (std::abs(state.dataSurface->Surface(curSurfNum).Azimuth - azimuth) < 1.) {
   12560          34 :                 facingAzimuth.emplace_back(iFace);
   12561             :             }
   12562             :         }
   12563          13 :         return facingAzimuth;
   12564             :     }
   12565             : 
   12566             :     // returns the index of the face of a polyhedron that is probably opposite of the face index provided
   12567          25 :     int findPossibleOppositeFace(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly, int const faceIndex)
   12568             :     {
   12569             :         // J. Glazer - March 2017
   12570             : 
   12571          25 :         int selectedSurNum = zonePoly.SurfaceFace(faceIndex).SurfNum;
   12572          25 :         Real64 selectedAzimuth = state.dataSurface->Surface(selectedSurNum).Azimuth;
   12573          25 :         Real64 oppositeAzimuth = fmod(selectedAzimuth + 180., 360.);
   12574          25 :         Real64 selectedArea = state.dataSurface->Surface(selectedSurNum).Area;
   12575          25 :         int selectedNumCorners = zonePoly.SurfaceFace(faceIndex).NSides;
   12576          25 :         int found = -1;
   12577             : 
   12578         160 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12579         151 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12580         453 :             if ((zonePoly.SurfaceFace(iFace).NSides == selectedNumCorners) &&
   12581         210 :                 (std::abs(state.dataSurface->Surface(curSurfNum).Area - selectedArea) < 0.01) &&
   12582          59 :                 (std::abs(state.dataSurface->Surface(curSurfNum).Azimuth - oppositeAzimuth) < 1.)) {
   12583          16 :                 found = iFace;
   12584          16 :                 break;
   12585             :             }
   12586             :         }
   12587          25 :         return found;
   12588             :     }
   12589             : 
   12590             :     // tests if the corners of one face of the polyhedron are the same distance from corners of another face
   12591          16 :     bool areCornersEquidistant(DataVectorTypes::Polyhedron const &zonePoly, int const faceIndex, int const opFaceIndex, Real64 &distanceBetween)
   12592             :     {
   12593             :         // J. Glazer - March 2017
   12594             : 
   12595          16 :         Real64 tol = 0.0127; //  1.27 cm = 1/2 inch
   12596          16 :         bool allAreEquidistant = true;
   12597          16 :         Real64 firstDistance = -99.;
   12598          16 :         if (zonePoly.SurfaceFace(faceIndex).NSides == zonePoly.SurfaceFace(opFaceIndex).NSides) { // double check that the number of sides match
   12599          78 :             for (int iVertex = 1; iVertex <= zonePoly.SurfaceFace(faceIndex).NSides; ++iVertex) {
   12600          63 :                 int iVertexOpp = 1 + zonePoly.SurfaceFace(faceIndex).NSides - iVertex; // count backwards for opposite face
   12601             :                 Real64 curDistBetwCorners =
   12602          63 :                     distance(zonePoly.SurfaceFace(faceIndex).FacePoints(iVertex), zonePoly.SurfaceFace(opFaceIndex).FacePoints(iVertexOpp));
   12603          63 :                 if (iVertex == 1) {
   12604          16 :                     firstDistance = curDistBetwCorners;
   12605             :                 } else {
   12606          47 :                     if (std::abs(curDistBetwCorners - firstDistance) > tol) {
   12607           1 :                         allAreEquidistant = false;
   12608           1 :                         break;
   12609             :                     }
   12610             :                 }
   12611             :             }
   12612             :         } else {
   12613           0 :             allAreEquidistant = false;
   12614             :         }
   12615          16 :         if (allAreEquidistant) distanceBetween = firstDistance;
   12616          16 :         return allAreEquidistant;
   12617             :     }
   12618             : 
   12619             :     // test if two points in space are in the same position based on a small tolerance
   12620    19036619 :     bool isAlmostEqual3dPt(DataVectorTypes::Vector v1, DataVectorTypes::Vector v2)
   12621             :     {
   12622             :         // J. Glazer - March 2017
   12623             : 
   12624    19036619 :         Real64 tol = 0.0127; //  1.27 cm = 1/2 inch
   12625    19036619 :         return ((std::abs(v1.x - v2.x) < tol) && (std::abs(v1.y - v2.y) < tol) && (std::abs(v1.z - v2.z) < tol));
   12626             :     }
   12627             : 
   12628             :     // test if two points on a plane are in the same position based on a small tolerance
   12629         790 :     bool isAlmostEqual2dPt(DataVectorTypes::Vector_2d v1, DataVectorTypes::Vector_2d v2)
   12630             :     {
   12631             :         // J. Glazer - March 2017
   12632             : 
   12633         790 :         Real64 tol = 0.0127; //  1.27 cm = 1/2 inch
   12634         790 :         return ((std::abs(v1.x - v2.x) < tol) && (std::abs(v1.y - v2.y) < tol));
   12635             :     }
   12636             : 
   12637             :     // test if two points on a plane are in the same position based on a small tolerance (based on Vector2dCount comparison)
   12638           0 :     bool isAlmostEqual2dPt(DataVectorTypes::Vector2dCount v1, DataVectorTypes::Vector2dCount v2)
   12639             :     {
   12640             :         // J. Glazer - March 2017
   12641             : 
   12642           0 :         Real64 tol = 0.0127; //  1.27 cm = 1/2 inch
   12643           0 :         return ((std::abs(v1.x - v2.x) < tol) && (std::abs(v1.y - v2.y) < tol));
   12644             :     }
   12645             : 
   12646             :     // returns the index of vertex in a list that is in the same position in space as the given vertex
   12647      213580 :     int findIndexOfVertex(DataVectorTypes::Vector vertexToFind, std::vector<DataVectorTypes::Vector> listOfVertices)
   12648             :     {
   12649             :         // J. Glazer - March 2017
   12650             : 
   12651     1354988 :         for (std::size_t i = 0; i < listOfVertices.size(); i++) {
   12652     1354988 :             if (isAlmostEqual3dPt(listOfVertices[i], vertexToFind)) {
   12653      213580 :                 return i;
   12654             :             }
   12655             :         }
   12656           0 :         return -1;
   12657             :     }
   12658             : 
   12659             :     // returns the distance between two points in space
   12660     1013377 :     Real64 distance(DataVectorTypes::Vector v1, DataVectorTypes::Vector v2)
   12661             :     {
   12662             :         // J. Glazer - March 2017
   12663             : 
   12664     1013377 :         return sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2) + pow(v1.z - v2.z, 2));
   12665             :     }
   12666             : 
   12667     6788151 :     Real64 distanceFromPointToLine(DataVectorTypes::Vector start, DataVectorTypes::Vector end, DataVectorTypes::Vector test)
   12668             :     {
   12669             :         // np.linalg.norm(np.cross(e-s,p-s)/np.linalg.norm(e-s))
   12670    13576302 :         DataVectorTypes::Vector t = end - start;
   12671     6788151 :         t.normalize(); // Unit vector of start to end
   12672             : 
   12673    13576302 :         DataVectorTypes::Vector other = test - start;
   12674             : 
   12675    13576302 :         DataVectorTypes::Vector projection = DataVectorTypes::cross(t, other); // normal unit vector, that's the distance component
   12676    13576302 :         return projection.length();
   12677             :     }
   12678             : 
   12679             :     // tests if a point in space lies on the line segment defined by two other points
   12680     6788151 :     bool isPointOnLineBetweenPoints(DataVectorTypes::Vector start, DataVectorTypes::Vector end, DataVectorTypes::Vector test)
   12681             :     {
   12682             :         // J. Glazer - March 2017
   12683             :         // The tolerance has to be low enough. Take for eg a plenum that has an edge that's 30meters long, you risk adding point from the
   12684             :         // floor to the roof, cf #7383 compute the shortest distance from the point to the line first to avoid false positive
   12685     6788151 :         Real64 tol = 0.0127;
   12686     6788151 :         if (distanceFromPointToLine(start, end, test) < tol) { // distanceFromPointToLine always positive, it's calculated as norml_L2
   12687      281433 :             return (std::abs((distance(start, end) - (distance(start, test) + distance(test, end)))) < tol);
   12688             :         }
   12689     6506718 :         return false;
   12690             :     }
   12691             : 
   12692     1348559 :     bool EdgeOfSurf::operator==(const EdgeOfSurf &other) const
   12693             :     {
   12694     6727832 :         return ((isAlmostEqual3dPt(this->start, other.start) && isAlmostEqual3dPt(this->end, other.end)) ||
   12695     6732636 :                 (isAlmostEqual3dPt(this->start, other.end) && isAlmostEqual3dPt(this->end, other.start)));
   12696             :     }
   12697             : 
   12698           0 :     bool EdgeOfSurf::operator!=(const EdgeOfSurf &other) const
   12699             :     {
   12700           0 :         return !(*this == other);
   12701             :     }
   12702             : 
   12703     6110750 :     bool EdgeOfSurf::containsPoints(const Vector &vertex) const
   12704             :     {
   12705    36353080 :         return (!isAlmostEqual3dPt(this->start, vertex) && !isAlmostEqual3dPt(this->end, vertex) &&
   12706    36353080 :                 isPointOnLineBetweenPoints(this->start, this->end, vertex));
   12707             :     }
   12708             : 
   12709        6964 :     double EdgeOfSurf::length() const
   12710             :     {
   12711        6964 :         return distance(this->start, this->end);
   12712             :     }
   12713             : 
   12714       41478 :     void ProcessSurfaceVertices(EnergyPlusData &state, int const ThisSurf, bool &ErrorsFound)
   12715             :     {
   12716             : 
   12717             :         // SUBROUTINE INFORMATION:
   12718             :         //       AUTHOR         Legacy Code (Walton)
   12719             :         //       DATE WRITTEN   1976
   12720             :         //       MODIFIED        FW, Mar 2002: Add triangular windows
   12721             :         //                       FW, May 2002: modify test for 4-sided but non-rectangular subsurfaces
   12722             :         //                       FW, Sep 2002: add shape for base surfaces (walls and detached shading surfaces)
   12723             : 
   12724             :         // PURPOSE OF THIS SUBROUTINE:
   12725             :         // This subroutine processes each surface into the vertex representation used
   12726             :         // by the shading procedures.
   12727             : 
   12728             :         // METHODOLOGY EMPLOYED:
   12729             :         // Detached Shading, Base Surfaces, Attached Shading surfaces are represented in the
   12730             :         // same manner as original.  Subsurfaces (windows, doors) are a "relative coordinate".
   12731             : 
   12732             :         using namespace Vectors;
   12733             : 
   12734             :         static constexpr std::string_view RoutineName("ProcessSurfaceVertices: ");
   12735             : 
   12736             :         Real64 X1;           // Intermediate Result
   12737             :         Real64 Y1;           // Intermediate Result
   12738             :         Real64 Z1;           // Intermediate Result
   12739             :         Real64 XLLC;         // X-coordinate of lower left corner
   12740             :         Real64 YLLC;         // Y-coordinate of lower left corner
   12741             :         Real64 ZLLC;         // Z-coordinate of lower left corner
   12742             :         int n;               // Vertex Number in Loop
   12743             :         int ThisBaseSurface; // Current base surface
   12744             :         Real64 Xp;
   12745             :         Real64 Yp;
   12746             :         Real64 Zp;
   12747             :         Real64 SurfWorldAz; // Surface Azimuth (facing)
   12748             :         Real64 SurfTilt;    // Surface Tilt
   12749       41478 :         SurfaceShape ThisShape(SurfaceShape::None);
   12750             :         bool BaseSurface; // True if a base surface or a detached shading surface
   12751             :         Real64 ThisSurfAz;
   12752             :         Real64 ThisSurfTilt;
   12753             :         Real64 ThisReveal;
   12754             :         Real64 ThisWidth;
   12755             :         Real64 ThisHeight;
   12756             :         int FrDivNum;        // Frame/divider number
   12757             :         Real64 FrWidth;      // Frame width for exterior windows (m)
   12758             :         Real64 FrArea;       // Frame area for exterior windows(m2)
   12759             :         Real64 DivWidth;     // Divider width for exterior windows (m)
   12760             :         Real64 DivArea;      // Divider area for exterior windows (m2)
   12761             :         Real64 DivFrac;      // Fraction of divider area without overlaps
   12762             :         bool ErrorInSurface; // false/true, depending on pass through routine
   12763             :         bool SError;         // Bool used for return value of calls to PlaneEquation
   12764             :         bool HeatTransSurf;
   12765             :         bool IsCoPlanar;
   12766             :         Real64 OutOfLine;
   12767             :         int LastVertexInError;
   12768             : 
   12769             :         // Object Data
   12770       41478 :         PlaneEq BasePlane;
   12771       82956 :         Vector TVect;
   12772       82956 :         Vector CoordinateTransVector;
   12773             : 
   12774       41478 :         if (state.dataSurface->Surface(ThisSurf).VerticesProcessed) {
   12775           0 :             return;
   12776             :         }
   12777             : 
   12778       41478 :         ErrorInSurface = false;
   12779             : 
   12780       41478 :         if (state.dataSurfaceGeometry->ProcessSurfaceVerticesOneTimeFlag) {
   12781         742 :             state.dataSurfaceGeometry->Xpsv.allocate(state.dataSurface->MaxVerticesPerSurface);
   12782         742 :             state.dataSurfaceGeometry->Ypsv.allocate(state.dataSurface->MaxVerticesPerSurface);
   12783         742 :             state.dataSurfaceGeometry->Zpsv.allocate(state.dataSurface->MaxVerticesPerSurface);
   12784         742 :             state.dataSurfaceGeometry->Xpsv = 0.0;
   12785         742 :             state.dataSurfaceGeometry->Ypsv = 0.0;
   12786         742 :             state.dataSurfaceGeometry->Zpsv = 0.0;
   12787         742 :             state.dataSurfaceGeometry->ProcessSurfaceVerticesOneTimeFlag = false;
   12788             :         }
   12789             : 
   12790             :         // Categorize this surface
   12791             : 
   12792       41478 :         if (state.dataSurface->Surface(ThisSurf).BaseSurf == 0 || state.dataSurface->Surface(ThisSurf).BaseSurf == ThisSurf) {
   12793       35038 :             BaseSurface = true;
   12794             :         } else {
   12795        6440 :             BaseSurface = false;
   12796             :         }
   12797             : 
   12798       41478 :         ThisBaseSurface = state.dataSurface->Surface(ThisSurf).BaseSurf; // Dont know if this is still needed or not
   12799       41478 :         HeatTransSurf = state.dataSurface->Surface(ThisSurf).HeatTransSurf;
   12800             : 
   12801             :         // Kludge for daylighting shelves
   12802       41478 :         if (state.dataSurface->Surface(ThisSurf).IsShadowing) {
   12803        1542 :             ThisBaseSurface = ThisSurf;
   12804        1542 :             HeatTransSurf = true;
   12805             :         }
   12806             : 
   12807             :         // IF (Surface(ThisSurf)%Name(1:3) /= 'Mir') THEN
   12808       41478 :         if (!state.dataSurface->Surface(ThisSurf).MirroredSurf) {
   12809       81414 :             CalcCoPlanarNess(
   12810       81414 :                 state.dataSurface->Surface(ThisSurf).Vertex, state.dataSurface->Surface(ThisSurf).Sides, IsCoPlanar, OutOfLine, LastVertexInError);
   12811       40707 :             if (!IsCoPlanar) {
   12812           0 :                 if (OutOfLine > 0.01) {
   12813           0 :                     ShowSevereError(state,
   12814           0 :                                     format("{}Suspected non-planar surface:\"{}\", Max \"out of line\"={:.5T} at Vertex # {}",
   12815             :                                            RoutineName,
   12816           0 :                                            state.dataSurface->Surface(ThisSurf).Name,
   12817             :                                            OutOfLine,
   12818           0 :                                            LastVertexInError));
   12819             :                 } else {
   12820           0 :                     ShowWarningError(state,
   12821           0 :                                      format("{}Possible non-planar surface:\"{}\", Max \"out of line\"={:.5T} at Vertex # {}",
   12822             :                                             RoutineName,
   12823           0 :                                             state.dataSurface->Surface(ThisSurf).Name,
   12824             :                                             OutOfLine,
   12825           0 :                                             LastVertexInError));
   12826             :                 }
   12827             :                 //       ErrorInSurface=.TRUE.
   12828             :             }
   12829             :         }
   12830             : 
   12831       41478 :         if (BaseSurface) {
   12832       35038 :             SurfWorldAz = state.dataSurface->Surface(ThisSurf).Azimuth;
   12833       35038 :             SurfTilt = state.dataSurface->Surface(ThisSurf).Tilt;
   12834      175865 :             for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
   12835      140827 :                 state.dataSurfaceGeometry->Xpsv(n) = state.dataSurface->Surface(ThisSurf).Vertex(n).x;
   12836      140827 :                 state.dataSurfaceGeometry->Ypsv(n) = state.dataSurface->Surface(ThisSurf).Vertex(n).y;
   12837      140827 :                 state.dataSurfaceGeometry->Zpsv(n) = state.dataSurface->Surface(ThisSurf).Vertex(n).z;
   12838             :             }
   12839       35038 :             TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
   12840       35038 :             ThisWidth = VecLength(TVect);
   12841       35038 :             TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
   12842       35038 :             ThisHeight = VecLength(TVect);
   12843       35038 :             state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
   12844       35038 :             state.dataSurface->Surface(ThisSurf).Height = ThisHeight; // For a horizontal surface this is actually length!
   12845       35038 :             if (state.dataSurface->Surface(ThisSurf).Sides == 3) {
   12846         181 :                 state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Triangle;
   12847       34857 :             } else if (state.dataSurface->Surface(ThisSurf).Sides == 4) {
   12848             :                 // Test for rectangularity
   12849       34690 :                 if (isRectangle(state, ThisSurf)) {
   12850       29804 :                     state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Rectangle;
   12851             :                 } else {
   12852        4886 :                     state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Quadrilateral;
   12853             :                 }
   12854             :             } else { // Surface( ThisSurf ).Sides > 4
   12855         167 :                 state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Polygonal;
   12856         167 :                 if (std::abs(ThisHeight * ThisWidth - state.dataSurface->Surface(ThisSurf).GrossArea) > 0.001) {
   12857         167 :                     state.dataSurface->Surface(ThisSurf).Width = std::sqrt(state.dataSurface->Surface(ThisSurf).GrossArea);
   12858         167 :                     state.dataSurface->Surface(ThisSurf).Height = state.dataSurface->Surface(ThisSurf).Width;
   12859         167 :                     ThisWidth = state.dataSurface->Surface(ThisSurf).Width;
   12860         167 :                     ThisHeight = state.dataSurface->Surface(ThisSurf).Height;
   12861             :                 }
   12862             :             }
   12863             : 
   12864             :         } else { // It's a subsurface to previous basesurface in this set of calls
   12865             : 
   12866        6440 :             ThisSurfAz = state.dataSurface->Surface(ThisSurf).Azimuth;
   12867        6440 :             ThisSurfTilt = state.dataSurface->Surface(ThisSurf).Tilt;
   12868             : 
   12869             :             // Retrieve base surface info
   12870        6440 :             Real64 const baseSurfWorldAz = state.dataSurface->Surface(ThisBaseSurface).Azimuth;
   12871        6440 :             Real64 const baseSurfTilt = state.dataSurface->Surface(ThisBaseSurface).Tilt;
   12872        6440 :             Real64 const BaseCosAzimuth = std::cos(baseSurfWorldAz * DataGlobalConstants::DegToRadians);
   12873        6440 :             Real64 const BaseSinAzimuth = std::sin(baseSurfWorldAz * DataGlobalConstants::DegToRadians);
   12874        6440 :             Real64 const BaseCosTilt = std::cos(baseSurfTilt * DataGlobalConstants::DegToRadians);
   12875        6440 :             Real64 const BaseSinTilt = std::sin(baseSurfTilt * DataGlobalConstants::DegToRadians);
   12876        6440 :             Real64 const BaseXLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).x;
   12877        6440 :             Real64 const BaseYLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).y;
   12878        6440 :             Real64 const BaseZLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).z;
   12879             : 
   12880        6440 :             if (HeatTransSurf) {
   12881             : 
   12882        6440 :                 if (state.dataSurface->Surface(ThisSurf).Sides == 4) {
   12883        6438 :                     ThisShape = SurfaceShape::RectangularDoorWindow;
   12884           2 :                 } else if (state.dataSurface->Surface(ThisSurf).Sides == 3 && state.dataSurface->Surface(ThisSurf).Class == SurfaceClass::Window) {
   12885           2 :                     ThisShape = SurfaceShape::TriangularWindow;
   12886           0 :                 } else if (state.dataSurface->Surface(ThisSurf).Sides == 3 && state.dataSurface->Surface(ThisSurf).Class == SurfaceClass::Door) {
   12887           0 :                     ThisShape = SurfaceShape::TriangularDoor;
   12888             :                 } else {
   12889           0 :                     assert(false);
   12890             :                 }
   12891             : 
   12892             :             } else { //  this is a shadowing subsurface
   12893             : 
   12894           0 :                 if (std::abs(state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Tilt - ThisSurfTilt) <= 0.01) {
   12895             :                     // left or right fin
   12896           0 :                     if (ThisSurfAz < 0.0) ThisSurfAz += 360.0;
   12897           0 :                     if (ThisSurfAz > state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Azimuth) {
   12898           0 :                         ThisShape = SurfaceShape::RectangularLeftFin;
   12899             :                     } else {
   12900           0 :                         ThisShape = SurfaceShape::RectangularRightFin;
   12901             :                     }
   12902             :                 } else {
   12903           0 :                     ThisShape = SurfaceShape::RectangularOverhang;
   12904             :                 }
   12905             :             }
   12906             : 
   12907             :             // Setting relative coordinates for shadowing calculations for subsurfaces
   12908        6440 :             switch (ThisShape) {
   12909        6438 :             case SurfaceShape::RectangularDoorWindow: { // Rectangular heat transfer subsurface
   12910        6438 :                 PlaneEquation(state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Vertex,
   12911        6438 :                               state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Sides,
   12912             :                               BasePlane,
   12913             :                               SError);
   12914        6438 :                 if (SError) {
   12915           0 :                     ShowSevereError(state,
   12916           0 :                                     std::string{RoutineName} + "Degenerate surface (likely two vertices equal):\"" +
   12917           0 :                                         state.dataSurface->Surface(ThisSurf).Name + "\".");
   12918           0 :                     ErrorInSurface = true;
   12919             :                 }
   12920        6438 :                 ThisReveal = -Pt2Plane(state.dataSurface->Surface(ThisSurf).Vertex(2), BasePlane);
   12921        6438 :                 if (std::abs(ThisReveal) < 0.0002) ThisReveal = 0.0;
   12922        6438 :                 state.dataSurface->Surface(ThisSurf).Reveal = ThisReveal;
   12923        6438 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
   12924        6438 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
   12925        6438 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
   12926        6438 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   12927        6438 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   12928        6438 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   12929        6438 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
   12930        6438 :                 ThisWidth = VecLength(TVect);
   12931        6438 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
   12932        6438 :                 ThisHeight = VecLength(TVect);
   12933        6438 :                 state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
   12934        6438 :                 state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
   12935             : 
   12936             :                 // Processing of 4-sided but non-rectangular Window, Door or GlassDoor, for use in calc of convective air flow.
   12937        6438 :                 if (!isRectangle(state, ThisSurf)) {
   12938             : 
   12939             :                     // Transform the surface into an equivalent rectangular surface with the same area and aspect ratio.
   12940           1 :                     MakeEquivalentRectangle(state, ThisSurf, ErrorsFound);
   12941             : 
   12942           1 :                     if (state.dataGlobal->DisplayExtraWarnings) {
   12943           0 :                         ShowWarningError(state, std::string{RoutineName} + "Suspected 4-sided but non-rectangular Window, Door or GlassDoor:");
   12944           0 :                         ShowContinueError(state,
   12945           0 :                                           "Surface=" + state.dataSurface->Surface(ThisSurf).Name +
   12946             :                                               " is transformed into an equivalent rectangular surface with the same area and aspect ratio. ");
   12947             :                     }
   12948             :                 }
   12949             : 
   12950        6438 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   12951        6438 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   12952        6438 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
   12953        6438 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
   12954        6438 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC + state.dataSurface->Surface(ThisSurf).Height;
   12955        6438 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC + state.dataSurface->Surface(ThisSurf).Height;
   12956        6438 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC;
   12957        6438 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC;
   12958        6438 :                 state.dataSurfaceGeometry->Zpsv(1) = ZLLC;
   12959        6438 :                 state.dataSurfaceGeometry->Zpsv(2) = ZLLC;
   12960        6438 :                 state.dataSurfaceGeometry->Zpsv(3) = ZLLC;
   12961        6438 :                 state.dataSurfaceGeometry->Zpsv(4) = ZLLC;
   12962             : 
   12963       18848 :                 if (state.dataSurface->Surface(ThisSurf).Class == SurfaceClass::Window &&
   12964       12396 :                     state.dataSurface->Surface(ThisSurf).ExtBoundCond == ExternalEnvironment &&
   12965        5958 :                     state.dataSurface->Surface(ThisSurf).FrameDivider > 0) {
   12966         381 :                     FrDivNum = state.dataSurface->Surface(ThisSurf).FrameDivider;
   12967             :                     // Set flag for calculating beam solar reflection from outside and/or inside window reveal
   12968        1143 :                     if ((state.dataSurface->Surface(ThisSurf).Reveal > 0.0 && state.dataSurface->FrameDivider(FrDivNum).OutsideRevealSolAbs > 0.0) ||
   12969         381 :                         (state.dataSurface->FrameDivider(FrDivNum).InsideSillDepth > 0.0 &&
   12970         762 :                          state.dataSurface->FrameDivider(FrDivNum).InsideSillSolAbs > 0.0) ||
   12971         381 :                         (state.dataSurface->FrameDivider(FrDivNum).InsideReveal > 0.0 &&
   12972           0 :                          state.dataSurface->FrameDivider(FrDivNum).InsideRevealSolAbs > 0.0))
   12973           0 :                         state.dataHeatBal->CalcWindowRevealReflection = true;
   12974             : 
   12975             :                     // For exterior window with frame, subtract frame area from base surface
   12976             :                     // (only rectangular windows are allowed to have a frame and/or divider;
   12977             :                     // Surface(ThisSurf)%FrameDivider will be 0 for triangular windows)
   12978         381 :                     FrWidth = state.dataSurface->FrameDivider(FrDivNum).FrameWidth;
   12979         381 :                     if (FrWidth > 0.0) {
   12980         390 :                         FrArea = (state.dataSurface->Surface(ThisSurf).Height + 2.0 * FrWidth) *
   12981         130 :                                      (state.dataSurface->Surface(ThisSurf).Width + 2.0 * FrWidth) -
   12982         130 :                                  state.dataSurface->Surface(ThisSurf).Area / state.dataSurface->Surface(ThisSurf).Multiplier;
   12983         130 :                         state.dataSurface->SurfWinFrameArea(ThisSurf) = FrArea * state.dataSurface->Surface(ThisSurf).Multiplier;
   12984         390 :                         if ((state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Area -
   12985         260 :                              state.dataSurface->SurfWinFrameArea(ThisSurf)) <= 0.0) {
   12986           0 :                             ShowSevereError(state,
   12987           0 :                                             std::string{RoutineName} + "Base Surface=\"" +
   12988           0 :                                                 state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Name + "\", ");
   12989           0 :                             ShowContinueError(state,
   12990           0 :                                               "Window Surface=\"" + state.dataSurface->Surface(ThisSurf).Name +
   12991             :                                                   "\" area (with frame) is too large to fit on the surface.");
   12992           0 :                             ShowContinueError(state,
   12993           0 :                                               format("Base surface area (-windows and doors)=[{:.2T}] m2, frame area=[{:.2T}] m2.",
   12994           0 :                                                      state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Area,
   12995           0 :                                                      state.dataSurface->SurfWinFrameArea(ThisSurf)));
   12996           0 :                             ErrorInSurface = true;
   12997             :                         }
   12998         130 :                         state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Area -=
   12999         130 :                             state.dataSurface->SurfWinFrameArea(ThisSurf);
   13000             :                     }
   13001             :                     // If exterior window has divider, subtract divider area to get glazed area
   13002         381 :                     DivWidth = state.dataSurface->FrameDivider(state.dataSurface->Surface(ThisSurf).FrameDivider).DividerWidth;
   13003         381 :                     if (DivWidth > 0.0 && !ErrorInSurface) {
   13004         192 :                         DivArea = DivWidth * (state.dataSurface->FrameDivider(FrDivNum).HorDividers * state.dataSurface->Surface(ThisSurf).Width +
   13005         128 :                                               state.dataSurface->FrameDivider(FrDivNum).VertDividers * state.dataSurface->Surface(ThisSurf).Height -
   13006         128 :                                               state.dataSurface->FrameDivider(FrDivNum).HorDividers *
   13007         128 :                                                   state.dataSurface->FrameDivider(FrDivNum).VertDividers * DivWidth);
   13008          64 :                         state.dataSurface->SurfWinDividerArea(ThisSurf) = DivArea * state.dataSurface->Surface(ThisSurf).Multiplier;
   13009          64 :                         if ((state.dataSurface->Surface(ThisSurf).Area - state.dataSurface->SurfWinDividerArea(ThisSurf)) <= 0.0) {
   13010           0 :                             ShowSevereError(state,
   13011           0 :                                             std::string{RoutineName} + "Divider area exceeds glazed opening for window " +
   13012           0 :                                                 state.dataSurface->Surface(ThisSurf).Name);
   13013           0 :                             ShowContinueError(state,
   13014           0 :                                               format("Window surface area=[{:.2T}] m2, divider area=[{:.2T}] m2.",
   13015           0 :                                                      state.dataSurface->Surface(ThisSurf).Area,
   13016           0 :                                                      state.dataSurface->SurfWinDividerArea(ThisSurf)));
   13017           0 :                             ErrorInSurface = true;
   13018             :                         }
   13019          64 :                         state.dataSurface->Surface(ThisSurf).Area -= state.dataSurface->SurfWinDividerArea(ThisSurf); // Glazed area
   13020          64 :                         if (DivArea <= 0.0) {
   13021           0 :                             ShowWarningError(state,
   13022           0 :                                              std::string{RoutineName} +
   13023           0 :                                                  "Calculated Divider Area <= 0.0 for Window=" + state.dataSurface->Surface(ThisSurf).Name);
   13024           0 :                             if (state.dataSurface->FrameDivider(FrDivNum).HorDividers == 0) {
   13025           0 :                                 ShowContinueError(state, "..Number of Horizontal Dividers = 0.");
   13026             :                             }
   13027           0 :                             if (state.dataSurface->FrameDivider(FrDivNum).VertDividers == 0) {
   13028           0 :                                 ShowContinueError(state, "..Number of Vertical Dividers = 0.");
   13029             :                             }
   13030             :                         } else {
   13031          64 :                             state.dataSurface->SurfWinGlazedFrac(ThisSurf) =
   13032         128 :                                 state.dataSurface->Surface(ThisSurf).Area /
   13033          64 :                                 (state.dataSurface->Surface(ThisSurf).Area + state.dataSurface->SurfWinDividerArea(ThisSurf));
   13034             :                             // Correction factor for portion of divider subject to divider projection correction
   13035         192 :                             DivFrac = (1.0 - state.dataSurface->FrameDivider(FrDivNum).HorDividers *
   13036         128 :                                                  state.dataSurface->FrameDivider(FrDivNum).VertDividers * pow_2(DivWidth) / DivArea);
   13037          64 :                             state.dataSurface->SurfWinProjCorrDivOut(ThisSurf) =
   13038          64 :                                 DivFrac * state.dataSurface->FrameDivider(FrDivNum).DividerProjectionOut / DivWidth;
   13039          64 :                             state.dataSurface->SurfWinProjCorrDivIn(ThisSurf) =
   13040          64 :                                 DivFrac * state.dataSurface->FrameDivider(FrDivNum).DividerProjectionIn / DivWidth;
   13041             :                             // Correction factor for portion of frame subject to frame projection correction
   13042          64 :                             if (FrWidth > 0.0) {
   13043          64 :                                 state.dataSurface->SurfWinProjCorrFrOut(ThisSurf) =
   13044         128 :                                     (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionOut / FrWidth) *
   13045         128 :                                     (ThisHeight + ThisWidth -
   13046         128 :                                      (state.dataSurface->FrameDivider(FrDivNum).HorDividers +
   13047         128 :                                       state.dataSurface->FrameDivider(FrDivNum).VertDividers) *
   13048          64 :                                          DivWidth) /
   13049          64 :                                     (ThisHeight + ThisWidth + 2 * FrWidth);
   13050          64 :                                 state.dataSurface->SurfWinProjCorrFrIn(ThisSurf) =
   13051         128 :                                     (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionIn / FrWidth) *
   13052         128 :                                     (ThisHeight + ThisWidth -
   13053         128 :                                      (state.dataSurface->FrameDivider(FrDivNum).HorDividers +
   13054         128 :                                       state.dataSurface->FrameDivider(FrDivNum).VertDividers) *
   13055          64 :                                          DivWidth) /
   13056          64 :                                     (ThisHeight + ThisWidth + 2 * FrWidth);
   13057             :                             }
   13058             :                         }
   13059             :                     }
   13060             :                 }
   13061        6438 :             } break;
   13062           2 :             case SurfaceShape::TriangularWindow:
   13063             :             case SurfaceShape::TriangularDoor: {
   13064           2 :                 PlaneEquation(state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Vertex,
   13065           2 :                               state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Sides,
   13066             :                               BasePlane,
   13067             :                               SError);
   13068           2 :                 if (SError) {
   13069           0 :                     ShowSevereError(state,
   13070           0 :                                     std::string{RoutineName} + "Degenerate surface (likely two vertices equal):\"" +
   13071           0 :                                         state.dataSurface->Surface(ThisSurf).Name + "\".");
   13072           0 :                     ErrorInSurface = true;
   13073             :                 }
   13074           2 :                 ThisReveal = -Pt2Plane(state.dataSurface->Surface(ThisSurf).Vertex(2), BasePlane);
   13075           2 :                 if (std::abs(ThisReveal) < 0.0002) ThisReveal = 0.0;
   13076           2 :                 state.dataSurface->Surface(ThisSurf).Reveal = ThisReveal;
   13077           2 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
   13078           2 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
   13079           2 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
   13080           2 :                 state.dataSurfaceGeometry->Xpsv(2) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13081           2 :                 state.dataSurfaceGeometry->Ypsv(2) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13082           2 :                 state.dataSurfaceGeometry->Zpsv(2) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13083           2 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
   13084           2 :                 ThisWidth = VecLength(TVect);
   13085           2 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
   13086           2 :                 ThisHeight = VecLength(TVect);
   13087           2 :                 state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
   13088           2 :                 state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
   13089             :                 // Effective height and width of a triangular window for use in calc of convective air flow
   13090             :                 // in gap between glass and shading device when shading device is present
   13091           2 :                 state.dataSurface->Surface(ThisSurf).Height =
   13092           2 :                     4.0 * state.dataSurface->Surface(ThisSurf).Area / (3.0 * state.dataSurface->Surface(ThisSurf).Width);
   13093           2 :                 state.dataSurface->Surface(ThisSurf).Width *= 0.75;
   13094             : 
   13095           2 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(1).x - BaseXLLC;
   13096           2 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(1).y - BaseYLLC;
   13097           2 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(1).z - BaseZLLC;
   13098           2 :                 state.dataSurfaceGeometry->Xpsv(1) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13099           2 :                 state.dataSurfaceGeometry->Ypsv(1) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13100           2 :                 state.dataSurfaceGeometry->Zpsv(1) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13101             : 
   13102           2 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(3).x - BaseXLLC;
   13103           2 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(3).y - BaseYLLC;
   13104           2 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(3).z - BaseZLLC;
   13105           2 :                 state.dataSurfaceGeometry->Xpsv(3) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13106           2 :                 state.dataSurfaceGeometry->Ypsv(3) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13107           2 :                 state.dataSurfaceGeometry->Zpsv(3) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13108           2 :             } break;
   13109           0 :             case SurfaceShape::RectangularOverhang: {
   13110           0 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
   13111           0 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
   13112           0 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
   13113           0 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13114           0 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13115           0 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13116           0 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
   13117           0 :                 ThisWidth = VecLength(TVect);
   13118           0 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
   13119           0 :                 ThisHeight = VecLength(TVect);
   13120           0 :                 state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
   13121           0 :                 state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
   13122           0 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13123           0 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13124           0 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
   13125           0 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
   13126           0 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC;
   13127           0 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC;
   13128           0 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC;
   13129           0 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC;
   13130           0 :                 state.dataSurfaceGeometry->Zpsv(1) = state.dataSurface->Surface(ThisSurf).Height;
   13131           0 :                 state.dataSurfaceGeometry->Zpsv(4) = state.dataSurface->Surface(ThisSurf).Height;
   13132           0 :                 state.dataSurfaceGeometry->Zpsv(2) = 0.0;
   13133           0 :                 state.dataSurfaceGeometry->Zpsv(3) = 0.0;
   13134           0 :             } break;
   13135           0 :             case SurfaceShape::RectangularLeftFin: {
   13136           0 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
   13137           0 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
   13138           0 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
   13139           0 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13140           0 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13141           0 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13142           0 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
   13143           0 :                 ThisWidth = VecLength(TVect);
   13144           0 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
   13145           0 :                 ThisHeight = VecLength(TVect);
   13146           0 :                 state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
   13147           0 :                 state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
   13148           0 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13149           0 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13150           0 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC;
   13151           0 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC;
   13152           0 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC;
   13153           0 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC;
   13154           0 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
   13155           0 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
   13156           0 :                 state.dataSurfaceGeometry->Zpsv(1) = state.dataSurface->Surface(ThisSurf).Height;
   13157           0 :                 state.dataSurfaceGeometry->Zpsv(4) = state.dataSurface->Surface(ThisSurf).Height;
   13158           0 :                 state.dataSurfaceGeometry->Zpsv(2) = 0.0;
   13159           0 :                 state.dataSurfaceGeometry->Zpsv(3) = 0.0;
   13160           0 :             } break;
   13161           0 :             case SurfaceShape::RectangularRightFin: {
   13162           0 :                 Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
   13163           0 :                 Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
   13164           0 :                 Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
   13165           0 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13166           0 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13167           0 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13168           0 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
   13169           0 :                 ThisWidth = VecLength(TVect);
   13170           0 :                 TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
   13171           0 :                 ThisHeight = VecLength(TVect);
   13172           0 :                 state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
   13173           0 :                 state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
   13174           0 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13175           0 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13176           0 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC;
   13177           0 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC;
   13178           0 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
   13179           0 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
   13180           0 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC;
   13181           0 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC;
   13182           0 :                 state.dataSurfaceGeometry->Zpsv(1) = state.dataSurface->Surface(ThisSurf).Height;
   13183           0 :                 state.dataSurfaceGeometry->Zpsv(4) = state.dataSurface->Surface(ThisSurf).Height;
   13184           0 :                 state.dataSurfaceGeometry->Zpsv(2) = 0.0;
   13185           0 :                 state.dataSurfaceGeometry->Zpsv(3) = 0.0;
   13186           0 :             } break;
   13187           0 :             default: {
   13188             :                 // Error Condition
   13189           0 :                 ShowSevereError(state, std::string{RoutineName} + "Incorrect surface shape number.", OptionalOutputFileRef{state.files.eso});
   13190           0 :                 ShowContinueError(state, "Please notify EnergyPlus support of this error and send input file.");
   13191           0 :                 ErrorInSurface = true;
   13192           0 :             } break;
   13193             :             }
   13194             : 
   13195       32198 :             for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
   13196             :                 // if less than 1/10 inch
   13197       25758 :                 state.dataSurfaceGeometry->Xpsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Xpsv(n)) / 10000.0;
   13198       25758 :                 if (std::abs(state.dataSurfaceGeometry->Xpsv(n)) < 0.0025) state.dataSurfaceGeometry->Xpsv(n) = 0.0;
   13199       25758 :                 state.dataSurfaceGeometry->Ypsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Ypsv(n)) / 10000.0;
   13200       25758 :                 if (std::abs(state.dataSurfaceGeometry->Ypsv(n)) < 0.0025) state.dataSurfaceGeometry->Ypsv(n) = 0.0;
   13201       25758 :                 state.dataSurfaceGeometry->Zpsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Zpsv(n)) / 10000.0;
   13202       25758 :                 if (std::abs(state.dataSurfaceGeometry->Zpsv(n)) < 0.0025) state.dataSurfaceGeometry->Zpsv(n) = 0.0;
   13203             :             }
   13204             : 
   13205        6440 :             state.dataSurface->Surface(ThisSurf).Shape = ThisShape;
   13206             : 
   13207             :         } // End of check if ThisSurf is a base surface
   13208             : 
   13209       41478 :         if (ErrorInSurface) {
   13210           0 :             ErrorsFound = true;
   13211           0 :             return;
   13212             :         }
   13213             : 
   13214             :         // Transfer to XV,YV,ZV arrays
   13215             : 
   13216       41478 :         state.dataSurface->ShadeV(ThisSurf).NVert = state.dataSurface->Surface(ThisSurf).Sides;
   13217       41478 :         state.dataSurface->ShadeV(ThisSurf).XV.allocate(state.dataSurface->Surface(ThisSurf).Sides);
   13218       41478 :         state.dataSurface->ShadeV(ThisSurf).YV.allocate(state.dataSurface->Surface(ThisSurf).Sides);
   13219       41478 :         state.dataSurface->ShadeV(ThisSurf).ZV.allocate(state.dataSurface->Surface(ThisSurf).Sides);
   13220             : 
   13221      208063 :         for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
   13222             :             // if less than 1/10 inch
   13223      166585 :             state.dataSurface->ShadeV(ThisSurf).XV(n) = state.dataSurfaceGeometry->Xpsv(n);
   13224      166585 :             state.dataSurface->ShadeV(ThisSurf).YV(n) = state.dataSurfaceGeometry->Ypsv(n);
   13225      166585 :             state.dataSurface->ShadeV(ThisSurf).ZV(n) = state.dataSurfaceGeometry->Zpsv(n);
   13226             :         }
   13227             : 
   13228             :         // Process Surfaces According to Type of Coordinate Origin.
   13229       41478 :         if (BaseSurface) {
   13230             : 
   13231             :             // General Surfaces:
   13232       35038 :             CalcCoordinateTransformation(state, ThisSurf, CoordinateTransVector); // X00,Y00,Z00,X,Y,Z,A)    ! Compute Coordinate Transformation
   13233             : 
   13234             :             // RECORD DIRECTION COSINES.
   13235       35038 :             if (HeatTransSurf) { // This is a general surface but not detached shading surface
   13236             : 
   13237             :                 // RECORD COORDINATE TRANSFORMATION FOR BASE SURFACES.
   13238       35024 :                 state.dataSurface->X0(ThisBaseSurface) = CoordinateTransVector.x;
   13239       35024 :                 state.dataSurface->Y0(ThisBaseSurface) = CoordinateTransVector.y;
   13240       35024 :                 state.dataSurface->Z0(ThisBaseSurface) = CoordinateTransVector.z;
   13241             : 
   13242             :                 // COMPUTE INVERSE TRANSFORMATION.
   13243       35024 :                 X1 = state.dataSurfaceGeometry->Xpsv(2) - CoordinateTransVector.x;
   13244       35024 :                 Y1 = state.dataSurfaceGeometry->Ypsv(2) - CoordinateTransVector.y;
   13245       35024 :                 Z1 = state.dataSurfaceGeometry->Zpsv(2) - CoordinateTransVector.z;
   13246             :                 // Store the relative coordinate shift values for later use by any subsurfaces
   13247      105072 :                 state.dataSurface->Surface(ThisBaseSurface).XShift = state.dataSurface->Surface(ThisBaseSurface).lcsx.x * X1 +
   13248       70048 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsx.y * Y1 +
   13249       35024 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsx.z * Z1;
   13250      105072 :                 state.dataSurface->Surface(ThisBaseSurface).YShift = state.dataSurface->Surface(ThisBaseSurface).lcsy.x * X1 +
   13251       70048 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsy.y * Y1 +
   13252       35024 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsy.z * Z1;
   13253       35024 :                 state.dataSurface->Surface(ThisBaseSurface).VerticesProcessed = true;
   13254             :             }
   13255             : 
   13256             :             // SUBSURFACES: (Surface(ThisSurf)%BaseSurf /= ThisSurf)
   13257             :         } else {
   13258             :             // WINDOWS OR DOORS:
   13259             : 
   13260             :             // SHIFT RELATIVE COORDINATES FROM LOWER LEFT CORNER TO ORIGIN DEFINED
   13261             :             // BY CTRAN AND SET DIRECTION COSINES SAME AS BASE SURFACE.
   13262        6440 :             if (!state.dataSurface->Surface(ThisBaseSurface).VerticesProcessed) {
   13263             : 
   13264           0 :                 if (state.dataSurface->Surface(ThisSurf).IsAirBoundarySurf) {
   13265           0 :                     ProcessSurfaceVertices(state, ThisBaseSurface, ErrorsFound);
   13266             :                 } else {
   13267             : 
   13268           0 :                     ShowSevereError(state, std::string{RoutineName} + "Developer error for Subsurface=" + state.dataSurface->Surface(ThisSurf).Name);
   13269           0 :                     ShowContinueError(state,
   13270           0 :                                       "Base surface=" + state.dataSurface->Surface(ThisBaseSurface).Name +
   13271             :                                           " vertices must be processed before any subsurfaces.");
   13272           0 :                     ShowFatalError(state, std::string{RoutineName});
   13273             :                 }
   13274             :             }
   13275             : 
   13276       32198 :             for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
   13277       25758 :                 state.dataSurface->ShadeV(ThisSurf).XV(n) += state.dataSurface->Surface(ThisBaseSurface).XShift;
   13278       25758 :                 state.dataSurface->ShadeV(ThisSurf).YV(n) += state.dataSurface->Surface(ThisBaseSurface).YShift;
   13279             :             }
   13280             :         }
   13281             : 
   13282       41478 :         if (ErrorInSurface) {
   13283           0 :             ErrorsFound = true;
   13284             :         }
   13285             :     }
   13286             : 
   13287       35038 :     void CalcCoordinateTransformation(EnergyPlusData &state,
   13288             :                                       int const SurfNum,            // Surface Number
   13289             :                                       Vector &CompCoordTranslVector // Coordinate Translation Vector
   13290             :     )
   13291             :     {
   13292             : 
   13293             :         // SUBROUTINE INFORMATION:
   13294             :         //       AUTHOR         George Walton, BLAST
   13295             :         //       DATE WRITTEN   August 1976
   13296             :         //       MODIFIED       LKL, May 2004 -- >4 sided polygons
   13297             :         //       RE-ENGINEERED  Yes
   13298             : 
   13299             :         // PURPOSE OF THIS SUBROUTINE:
   13300             :         // This subroutine develops a coordinate transformation such that the X-axis goes
   13301             :         // through points 2 and 3 and the Y-axis goes through point 1
   13302             :         // of a plane figure in 3-d space.
   13303             : 
   13304             :         // METHODOLOGY EMPLOYED:
   13305             :         // na
   13306             : 
   13307             :         // REFERENCES:
   13308             :         // 'NECAP' - NASA'S Energy-Cost Analysis Program
   13309             : 
   13310             :         // Using/Aliasing
   13311             :         using namespace Vectors;
   13312             : 
   13313             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   13314             :         int I;        // Loop Control
   13315             :         Real64 Gamma; // Intermediate Result
   13316             :         Real64 DotSelfX23;
   13317             : 
   13318             :         // Object Data
   13319       70076 :         Vector x21;
   13320       70076 :         Vector x23;
   13321             : 
   13322             :         // Determine Components of the Coordinate Translation Vector.
   13323             : 
   13324       35038 :         x21 = state.dataSurface->Surface(SurfNum).Vertex(2) - state.dataSurface->Surface(SurfNum).Vertex(1);
   13325       35038 :         x23 = state.dataSurface->Surface(SurfNum).Vertex(2) - state.dataSurface->Surface(SurfNum).Vertex(3);
   13326             : 
   13327       35038 :         DotSelfX23 = magnitude_squared(x23);
   13328             : 
   13329       35038 :         if (DotSelfX23 <= .1e-6) {
   13330           0 :             ShowSevereError(state,
   13331           0 :                             "CalcCoordinateTransformation: Invalid dot product, surface=\"" + state.dataSurface->Surface(SurfNum).Name + "\":");
   13332           0 :             for (I = 1; I <= state.dataSurface->Surface(SurfNum).Sides; ++I) {
   13333           0 :                 auto const &point{state.dataSurface->Surface(SurfNum).Vertex(I)};
   13334           0 :                 ShowContinueError(state, format(" ({:8.3F},{:8.3F},{:8.3F})", point.x, point.y, point.z));
   13335             :             }
   13336           0 :             ShowFatalError(
   13337           0 :                 state, "CalcCoordinateTransformation: Program terminates due to preceding condition.", OptionalOutputFileRef{state.files.eso});
   13338           0 :             return;
   13339             :         }
   13340             : 
   13341       35038 :         Gamma = dot(x21, x23) / magnitude_squared(x23);
   13342             : 
   13343       35038 :         CompCoordTranslVector = state.dataSurface->Surface(SurfNum).Vertex(2) +
   13344       70076 :                                 Gamma * (state.dataSurface->Surface(SurfNum).Vertex(3) - state.dataSurface->Surface(SurfNum).Vertex(2));
   13345             :     }
   13346             : 
   13347          18 :     void CreateShadedWindowConstruction(EnergyPlusData &state,
   13348             :                                         int const SurfNum,          // Surface number
   13349             :                                         int const WSCPtr,           // Pointer to WindowShadingControl for SurfNum
   13350             :                                         int const ShDevNum,         // Shading device material number for WSCptr
   13351             :                                         int const shadeControlIndex // index to the Surface().windowShadingControlList,
   13352             :                                                                     // Surface().shadedConstructionList, and Surface().shadedStormWinConstructionList
   13353             :     )
   13354             :     {
   13355             : 
   13356             :         // SUBROUTINE INFORMATION:
   13357             :         //       AUTHOR         Fred Winkelmann
   13358             :         //       DATE WRITTEN   Nov 2001
   13359             :         //       MODIFIED       na
   13360             :         //       RE-ENGINEERED  na
   13361             : 
   13362             :         // PURPOSE OF THIS SUBROUTINE:
   13363             :         // Creates a shaded window construction for windows whose WindowShadingControl
   13364             :         // has a shading device specified instead of a shaded construction
   13365             : 
   13366             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   13367             :         int ConstrNum;            // Number of unshaded construction
   13368             :         int ConstrNewSh;          // Number of shaded construction that is created
   13369          36 :         std::string ShDevName;    // Shading device material name
   13370          36 :         std::string ConstrName;   // Unshaded construction name
   13371          36 :         std::string ConstrNameSh; // Shaded construction name
   13372             :         int TotLayersOld;         // Total layers in old (unshaded) construction
   13373             :         int TotLayersNew;         // Total layers in new (shaded) construction
   13374             :         //  INTEGER :: loop                            ! DO loop index
   13375             : 
   13376          18 :         ShDevName = state.dataMaterial->Material(ShDevNum).Name;
   13377          18 :         ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
   13378          18 :         ConstrName = state.dataConstruction->Construct(ConstrNum).Name;
   13379          18 :         if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
   13380          18 :             ConstrNameSh = ConstrName + ':' + ShDevName + ":INT";
   13381             :         } else {
   13382           0 :             ConstrNameSh = ConstrName + ':' + ShDevName + ":EXT";
   13383             :         }
   13384             : 
   13385             :         // If this construction name already exists, set the surface's shaded construction number to it
   13386             : 
   13387          18 :         ConstrNewSh = UtilityRoutines::FindItemInList(ConstrNameSh, state.dataConstruction->Construct);
   13388             : 
   13389          18 :         if (ConstrNewSh > 0) {
   13390           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex] = ConstrNewSh;
   13391           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNewSh; // set the active to the current for now
   13392             :         } else {
   13393             : 
   13394             :             // Create new construction
   13395             : 
   13396          18 :             ConstrNewSh = state.dataHeatBal->TotConstructs + 1;
   13397          18 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex] = ConstrNewSh;
   13398          18 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNewSh; // set the active to the current for now
   13399          18 :             state.dataHeatBal->TotConstructs = ConstrNewSh;
   13400          18 :             state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
   13401          18 :             state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
   13402          18 :             state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs) = 0.0;
   13403          18 :             state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
   13404          18 :             state.dataHeatBal->NominalU(state.dataHeatBal->TotConstructs) = 0.0;
   13405          18 :             state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
   13406          18 :             state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
   13407             : 
   13408          18 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).setArraysBasedOnMaxSolidWinLayers(state);
   13409             : 
   13410          18 :             TotLayersOld = state.dataConstruction->Construct(ConstrNum).TotLayers;
   13411          18 :             TotLayersNew = TotLayersOld + 1;
   13412             : 
   13413          18 :             state.dataConstruction->Construct(ConstrNewSh).LayerPoint = 0;
   13414             : 
   13415          18 :             if (state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::IntShade ||
   13416           0 :                 state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::IntBlind) {
   13417             :                 // Interior shading device
   13418          18 :                 state.dataConstruction->Construct(ConstrNewSh).LayerPoint({1, TotLayersOld}) =
   13419          36 :                     state.dataConstruction->Construct(ConstrNum).LayerPoint({1, TotLayersOld});
   13420          18 :                 state.dataConstruction->Construct(ConstrNewSh).LayerPoint(TotLayersNew) = ShDevNum;
   13421          18 :                 state.dataConstruction->Construct(ConstrNewSh).InsideAbsorpSolar = state.dataMaterial->Material(ShDevNum).AbsorpSolar;
   13422          18 :                 state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpSolar =
   13423          18 :                     state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1)).AbsorpSolar;
   13424          18 :                 state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpThermal =
   13425          18 :                     state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1)).AbsorpThermalFront;
   13426             :             } else {
   13427             :                 // Exterior shading device
   13428           0 :                 state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1) = ShDevNum;
   13429           0 :                 state.dataConstruction->Construct(ConstrNewSh).LayerPoint({2, TotLayersNew}) =
   13430           0 :                     state.dataConstruction->Construct(ConstrNum).LayerPoint({1, TotLayersOld});
   13431           0 :                 state.dataConstruction->Construct(ConstrNewSh).InsideAbsorpSolar =
   13432           0 :                     state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(TotLayersNew)).AbsorpSolar;
   13433           0 :                 state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpSolar = state.dataMaterial->Material(ShDevNum).AbsorpSolar;
   13434           0 :                 state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpThermal = state.dataMaterial->Material(ShDevNum).AbsorpThermalFront;
   13435             :             }
   13436             :             // The following InsideAbsorpThermal applies only to inside glass; it is corrected
   13437             :             //  later in InitGlassOpticalCalculations if construction has inside shade or blind.
   13438          18 :             state.dataConstruction->Construct(ConstrNewSh).InsideAbsorpThermal =
   13439          18 :                 state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayersOld)).AbsorpThermalBack;
   13440          18 :             state.dataConstruction->Construct(ConstrNewSh).OutsideRoughness = DataSurfaces::SurfaceRoughness::VerySmooth;
   13441          18 :             state.dataConstruction->Construct(ConstrNewSh).DayltPropPtr = 0;
   13442          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFCross = 0.0;
   13443          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFFlux = 0.0;
   13444          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFInside = 0.0;
   13445          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFOutside = 0.0;
   13446          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFSourceIn = 0.0;
   13447          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFSourceOut = 0.0;
   13448          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTimeStep = 0.0;
   13449          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTSourceOut = 0.0;
   13450          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTSourceIn = 0.0;
   13451          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTSourceQ = 0.0;
   13452          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTUserOut = 0.0;
   13453          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTUserIn = 0.0;
   13454          18 :             state.dataConstruction->Construct(ConstrNewSh).CTFTUserSource = 0.0;
   13455          18 :             state.dataConstruction->Construct(ConstrNewSh).NumHistories = 0;
   13456          18 :             state.dataConstruction->Construct(ConstrNewSh).NumCTFTerms = 0;
   13457          18 :             state.dataConstruction->Construct(ConstrNewSh).UValue = 0.0;
   13458          18 :             state.dataConstruction->Construct(ConstrNewSh).SourceSinkPresent = false;
   13459          18 :             state.dataConstruction->Construct(ConstrNewSh).SolutionDimensions = 0;
   13460          18 :             state.dataConstruction->Construct(ConstrNewSh).SourceAfterLayer = 0;
   13461          18 :             state.dataConstruction->Construct(ConstrNewSh).TempAfterLayer = 0;
   13462          18 :             state.dataConstruction->Construct(ConstrNewSh).ThicknessPerpend = 0.0;
   13463          18 :             state.dataConstruction->Construct(ConstrNewSh).AbsDiff = 0.0;
   13464          18 :             state.dataConstruction->Construct(ConstrNewSh).AbsDiffBack = 0.0;
   13465          18 :             state.dataConstruction->Construct(ConstrNewSh).AbsDiffShade = 0.0;
   13466          18 :             state.dataConstruction->Construct(ConstrNewSh).AbsDiffBackShade = 0.0;
   13467          18 :             state.dataConstruction->Construct(ConstrNewSh).ShadeAbsorpThermal = 0.0;
   13468          18 :             state.dataConstruction->Construct(ConstrNewSh).AbsBeamShadeCoef = 0.0;
   13469          18 :             state.dataConstruction->Construct(ConstrNewSh).TransDiff = 0.0;
   13470          18 :             state.dataConstruction->Construct(ConstrNewSh).TransDiffVis = 0.0;
   13471          18 :             state.dataConstruction->Construct(ConstrNewSh).ReflectSolDiffBack = 0.0;
   13472          18 :             state.dataConstruction->Construct(ConstrNewSh).ReflectSolDiffFront = 0.0;
   13473          18 :             state.dataConstruction->Construct(ConstrNewSh).ReflectVisDiffBack = 0.0;
   13474          18 :             state.dataConstruction->Construct(ConstrNewSh).ReflectVisDiffFront = 0.0;
   13475          18 :             state.dataConstruction->Construct(ConstrNewSh).TransSolBeamCoef = 0.0;
   13476          18 :             state.dataConstruction->Construct(ConstrNewSh).TransVisBeamCoef = 0.0;
   13477          18 :             state.dataConstruction->Construct(ConstrNewSh).ReflSolBeamFrontCoef = 0.0;
   13478          18 :             state.dataConstruction->Construct(ConstrNewSh).ReflSolBeamBackCoef = 0.0;
   13479          18 :             state.dataConstruction->Construct(ConstrNewSh).W5FrameDivider = 0;
   13480          18 :             state.dataConstruction->Construct(ConstrNewSh).FromWindow5DataFile = false;
   13481             : 
   13482          18 :             state.dataConstruction->Construct(ConstrNewSh).Name = ConstrNameSh;
   13483          18 :             state.dataConstruction->Construct(ConstrNewSh).TotLayers = TotLayersNew;
   13484          18 :             state.dataConstruction->Construct(ConstrNewSh).TotSolidLayers = state.dataConstruction->Construct(ConstrNum).TotSolidLayers + 1;
   13485          18 :             state.dataConstruction->Construct(ConstrNewSh).TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
   13486          18 :             state.dataConstruction->Construct(ConstrNewSh).TypeIsWindow = true;
   13487          18 :             state.dataConstruction->Construct(ConstrNewSh).IsUsed = true;
   13488             : 
   13489         144 :             for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
   13490         882 :                 for (int index = 1; index <= DataSurfaces::MaxPolyCoeff; ++index) {
   13491         756 :                     state.dataConstruction->Construct(ConstrNewSh).AbsBeamCoef(Layer)(index) = 0.0;
   13492         756 :                     state.dataConstruction->Construct(ConstrNewSh).AbsBeamBackCoef(Layer)(index) = 0.0;
   13493             :                 }
   13494             :             }
   13495             :         }
   13496          18 :     }
   13497             : 
   13498           1 :     void CreateStormWindowConstructions(EnergyPlusData &state)
   13499             :     {
   13500             :         // For windows with an associated StormWindow object, creates a construction
   13501             :         // consisting of the base construction plus a storm window and air gap on the outside.
   13502             :         // If the window has an interior or between-glass shade/blind, also creates a
   13503             :         // construction consisting of the storm window added to the shaded construction.
   13504           1 :         DisplayString(state, "Creating Storm Window Constructions");
   13505             : 
   13506           2 :         for (int StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
   13507           1 :             int SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum; // Surface number
   13508           1 :             int ConstrNum = state.dataSurface->Surface(SurfNum).Construction;        // Number of unshaded construction
   13509             :             // Fatal error if base construction has more than three glass layers
   13510           1 :             if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers > 3) {
   13511           0 :                 ShowFatalError(
   13512           0 :                     state, "Window=" + state.dataSurface->Surface(SurfNum).Name + " has more than 3 glass layers; a storm window cannot be applied.");
   13513             :             }
   13514             : 
   13515             :             // create unshaded construction with storm window
   13516           2 :             const auto ChrNum = fmt::to_string(StormWinNum);
   13517           2 :             std::string ConstrNameSt = "BARECONSTRUCTIONWITHSTORMWIN:" + ChrNum; // Name of unshaded construction with storm window
   13518             :             // If this construction name already exists, set the surface's storm window construction number to it
   13519             :             int ConstrNewSt =
   13520           2 :                 UtilityRoutines::FindItemInList(ConstrNameSt,
   13521           1 :                                                 state.dataConstruction->Construct,
   13522           2 :                                                 state.dataHeatBal->TotConstructs); // Number of unshaded storm window construction that is created
   13523             :             // If necessary, create new material corresponding to the air layer between the storm winddow and the rest of the window
   13524           1 :             int MatNewStAir = createAirMaterialFromDistance(state, state.dataSurface->StormWindow(StormWinNum).StormWinDistance, "AIR:STORMWIN:");
   13525           1 :             if (ConstrNewSt == 0) {
   13526           1 :                 ConstrNewSt = createConstructionWithStorm(
   13527           1 :                     state, ConstrNum, ConstrNameSt, state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum, MatNewStAir);
   13528             :             }
   13529           1 :             state.dataSurface->SurfWinStormWinConstr(SurfNum) = ConstrNewSt;
   13530             : 
   13531             :             // create shaded constructions with storm window
   13532           2 :             state.dataSurface->Surface(SurfNum).shadedStormWinConstructionList.resize(
   13533           1 :                 state.dataSurface->Surface(SurfNum).shadedConstructionList.size(),
   13534             :                 0); // make the shaded storm window size the same size as the number of shaded constructions
   13535           1 :             for (std::size_t iConstruction = 0; iConstruction < state.dataSurface->Surface(SurfNum).shadedConstructionList.size(); ++iConstruction) {
   13536           0 :                 int curConstruction = state.dataSurface->Surface(SurfNum).shadedConstructionList[iConstruction];
   13537             :                 // Set ShAndSt, which is true if the window has a shaded construction to which a storm window
   13538             :                 // can be added. (A storm window can be added if there is an interior shade or blind and up to three
   13539             :                 // glass layers, or there is a between-glass shade or blind and two glass layers.)
   13540           0 :                 bool ShAndSt = false; // True if unshaded and shaded window can have a storm window
   13541           0 :                 std::string ConstrNameSh = state.dataConstruction->Construct(curConstruction).Name; // Name of original shaded window construction
   13542           0 :                 int TotLayers = state.dataConstruction->Construct(curConstruction).TotLayers;       // Total layers in a construction
   13543           0 :                 int MatIntSh = state.dataConstruction->Construct(curConstruction).LayerPoint(TotLayers); // Material number of interior shade or blind
   13544           0 :                 int MatBetweenGlassSh = 0; // Material number of between-glass shade or blind
   13545           0 :                 if (TotLayers == 5) MatBetweenGlassSh = state.dataConstruction->Construct(curConstruction).LayerPoint(3);
   13546           0 :                 if (state.dataConstruction->Construct(curConstruction).TotGlassLayers <= 3 &&
   13547           0 :                     (state.dataMaterial->Material(MatIntSh).Group == DataHeatBalance::MaterialGroup::Shade ||
   13548           0 :                      state.dataMaterial->Material(MatIntSh).Group == DataHeatBalance::MaterialGroup::WindowBlind))
   13549           0 :                     ShAndSt = true;
   13550           0 :                 if (MatBetweenGlassSh > 0) {
   13551           0 :                     if (state.dataMaterial->Material(MatBetweenGlassSh).Group == DataHeatBalance::MaterialGroup::Shade ||
   13552           0 :                         state.dataMaterial->Material(MatBetweenGlassSh).Group == DataHeatBalance::MaterialGroup::WindowBlind) {
   13553           0 :                         ShAndSt = true;
   13554             :                     } else {
   13555           0 :                         ShowContinueError(state,
   13556           0 :                                           "Window=" + state.dataSurface->Surface(SurfNum).Name +
   13557             :                                               " has a shaded construction to which a storm window cannot be applied.");
   13558           0 :                         ShowContinueError(state, "Storm windows can only be applied to shaded constructions that:");
   13559           0 :                         ShowContinueError(state, "have an interior shade or blind and up to three glass layers, or");
   13560           0 :                         ShowContinueError(state, "have a between-glass shade or blind and two glass layers.");
   13561           0 :                         ShowFatalError(state, "EnergyPlus is exiting due to reason stated above.");
   13562             :                     }
   13563             :                 }
   13564           0 :                 if (ShAndSt) {
   13565           0 :                     std::string ConstrNameStSh = "SHADEDCONSTRUCTIONWITHSTORMWIN:" + state.dataConstruction->Construct(iConstruction).Name + ":" +
   13566           0 :                                                  ChrNum; // Name of shaded construction with storm window
   13567           0 :                     int ConstrNewStSh = createConstructionWithStorm(
   13568           0 :                         state, ConstrNum, ConstrNameStSh, state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum, MatNewStAir);
   13569           0 :                     state.dataSurface->Surface(SurfNum).shadedStormWinConstructionList[iConstruction] =
   13570             :                         ConstrNewStSh; // put in same index as the shaded constuction
   13571             :                 }
   13572             :             } // end of loop for shaded constructions
   13573             :         }     // end of loop over storm window objects
   13574           1 :     }
   13575             : 
   13576           1 :     int createAirMaterialFromDistance(EnergyPlusData &state, Real64 distance, std::string namePrefix)
   13577             :     {
   13578           1 :         int mmDistance = int(1000 * distance); // Thickness of air gap in mm (usually between storm window and rest of window)
   13579           2 :         std::string MatNameStAir = namePrefix + format("{}MM", mmDistance); // Name of created air layer material
   13580           1 :         int newAirMaterial = UtilityRoutines::FindItemInList(MatNameStAir, state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
   13581           1 :         if (newAirMaterial == 0) {
   13582             :             // Create new material
   13583           1 :             state.dataHeatBal->TotMaterials = state.dataHeatBal->TotMaterials + 1;
   13584           1 :             newAirMaterial = state.dataHeatBal->TotMaterials;
   13585           1 :             state.dataMaterial->Material.redimension(state.dataHeatBal->TotMaterials);
   13586           1 :             state.dataHeatBal->NominalR.redimension(state.dataHeatBal->TotMaterials);
   13587           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Name = MatNameStAir;
   13588           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Group = DataHeatBalance::MaterialGroup::WindowGas;
   13589           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Roughness = DataSurfaces::SurfaceRoughness::MediumRough;
   13590           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Conductivity = 0.0;
   13591           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Density = 0.0;
   13592           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).IsoMoistCap = 0.0;
   13593           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Porosity = 0.0;
   13594           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Resistance = 0.0;
   13595           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).SpecHeat = 0.0;
   13596           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ThermGradCoef = 0.0;
   13597           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Thickness = distance;
   13598           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).VaporDiffus = 0.0;
   13599           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasType = 0;
   13600           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCon = 0.0;
   13601           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasVis = 0.0;
   13602           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCp = 0.0;
   13603           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasWght = 0.0;
   13604           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasFract = 0.0;
   13605           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasType(1) = 1;
   13606           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GlassSpectralDataPtr = 0;
   13607           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).NumberOfGasesInMixture = 1;
   13608           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCon(1, 1) = 2.873e-3;
   13609           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCon(2, 1) = 7.760e-5;
   13610           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasVis(1, 1) = 3.723e-6;
   13611           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasVis(2, 1) = 4.940e-8;
   13612           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCp(1, 1) = 1002.737;
   13613           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCp(2, 1) = 1.2324e-2;
   13614           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasWght(1) = 28.97;
   13615           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasFract(1) = 1.0;
   13616           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpSolar = 0.0;
   13617           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpThermal = 0.0;
   13618           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpVisible = 0.0;
   13619           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Trans = 0.0;
   13620           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransVis = 0.0;
   13621           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GlassTransDirtFactor = 0.0;
   13622           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectShade = 0.0;
   13623           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectShadeVis = 0.0;
   13624           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpThermalBack = 0.0;
   13625           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpThermalFront = 0.0;
   13626           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolBeamBack = 0.0;
   13627           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolBeamFront = 0.0;
   13628           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolDiffBack = 0.0;
   13629           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolDiffFront = 0.0;
   13630           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisBeamBack = 0.0;
   13631           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisBeamFront = 0.0;
   13632           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisDiffBack = 0.0;
   13633           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisDiffFront = 0.0;
   13634           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransSolBeam = 0.0;
   13635           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransThermal = 0.0;
   13636           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransVisBeam = 0.0;
   13637           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).BlindDataPtr = 0;
   13638           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeToGlassDist = 0.0;
   13639           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeTopOpeningMult = 0.0;
   13640           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeBottomOpeningMult = 0.0;
   13641           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeLeftOpeningMult = 0.0;
   13642           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeRightOpeningMult = 0.0;
   13643           1 :             state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeAirFlowPermeability = 0.0;
   13644             :         }
   13645           2 :         return (newAirMaterial);
   13646             :     }
   13647             : 
   13648             :     // create a new construction with storm based on an old construction and storm and gap materials
   13649           1 :     int createConstructionWithStorm(EnergyPlusData &state, int oldConstruction, std::string name, int stormMaterial, int gapMaterial)
   13650             :     {
   13651             :         int newConstruct =
   13652           2 :             UtilityRoutines::FindItemInList(name,
   13653           1 :                                             state.dataConstruction->Construct,
   13654           2 :                                             state.dataHeatBal->TotConstructs); // Number of shaded storm window construction that is created
   13655           1 :         if (newConstruct == 0) {
   13656           1 :             state.dataHeatBal->TotConstructs = state.dataHeatBal->TotConstructs + 1;
   13657           1 :             newConstruct = state.dataHeatBal->TotConstructs;
   13658           1 :             state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
   13659           1 :             state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
   13660           1 :             state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
   13661           1 :             state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
   13662           1 :             state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
   13663             : 
   13664             :             // these Construct arrays dimensioned based on MaxSolidWinLayers
   13665           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).setArraysBasedOnMaxSolidWinLayers(state);
   13666             : 
   13667           1 :             int TotLayersOld = state.dataConstruction->Construct(oldConstruction).TotLayers;
   13668           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint({1, Construction::MaxLayersInConstruct}) = 0;
   13669           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint(1) = stormMaterial;
   13670           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint(2) = gapMaterial;
   13671           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint({3, TotLayersOld + 2}) =
   13672           2 :                 state.dataConstruction->Construct(oldConstruction).LayerPoint({1, TotLayersOld});
   13673           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).Name = name;
   13674           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotLayers = TotLayersOld + 2;
   13675           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotSolidLayers =
   13676           1 :                 state.dataConstruction->Construct(oldConstruction).TotSolidLayers + 1;
   13677           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotGlassLayers =
   13678           1 :                 state.dataConstruction->Construct(oldConstruction).TotGlassLayers + 1;
   13679           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TypeIsWindow = true;
   13680           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).InsideAbsorpVis = 0.0;
   13681           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideAbsorpVis = 0.0;
   13682           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).InsideAbsorpSolar = 0.0;
   13683           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideAbsorpSolar = 0.0;
   13684           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).InsideAbsorpThermal =
   13685           1 :                 state.dataConstruction->Construct(oldConstruction).InsideAbsorpThermal;
   13686           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideAbsorpThermal =
   13687           1 :                 state.dataMaterial->Material(stormMaterial).AbsorpThermalFront;
   13688           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideRoughness = DataSurfaces::SurfaceRoughness::VerySmooth;
   13689           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).DayltPropPtr = 0;
   13690           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFCross = 0.0;
   13691           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFFlux = 0.0;
   13692           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFInside = 0.0;
   13693           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFOutside = 0.0;
   13694           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFSourceIn = 0.0;
   13695           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFSourceOut = 0.0;
   13696           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTimeStep = 0.0;
   13697           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTSourceOut = 0.0;
   13698           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTSourceIn = 0.0;
   13699           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTSourceQ = 0.0;
   13700           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTUserOut = 0.0;
   13701           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTUserIn = 0.0;
   13702           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTUserSource = 0.0;
   13703           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).NumHistories = 0;
   13704           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).NumCTFTerms = 0;
   13705           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).UValue = 0.0;
   13706           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).SourceSinkPresent = false;
   13707           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).SolutionDimensions = 0;
   13708           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).SourceAfterLayer = 0;
   13709           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TempAfterLayer = 0;
   13710           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ThicknessPerpend = 0.0;
   13711           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffIn = 0.0;
   13712           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffOut = 0.0;
   13713           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiff = 0.0;
   13714           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffBack = 0.0;
   13715           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffShade = 0.0;
   13716           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffBackShade = 0.0;
   13717           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ShadeAbsorpThermal = 0.0;
   13718           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsBeamShadeCoef = 0.0;
   13719           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransDiff = 0.0;
   13720           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransDiffVis = 0.0;
   13721           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectSolDiffBack = 0.0;
   13722           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectSolDiffFront = 0.0;
   13723           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectVisDiffBack = 0.0;
   13724           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectVisDiffFront = 0.0;
   13725           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransSolBeamCoef = 0.0;
   13726           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransVisBeamCoef = 0.0;
   13727           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflSolBeamFrontCoef = 0.0;
   13728           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflSolBeamBackCoef = 0.0;
   13729           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FrameDivider = 0;
   13730           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).FromWindow5DataFile = false;
   13731           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileMullionWidth = 0.0;
   13732           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileMullionOrientation =
   13733             :                 DataWindowEquivalentLayer::Orientation::Invalid;
   13734           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileGlazingSysWidth = 0.0;
   13735           1 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileGlazingSysHeight = 0.0;
   13736           8 :             for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
   13737          49 :                 for (int index = 1; index <= DataSurfaces::MaxPolyCoeff; ++index) {
   13738          42 :                     state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsBeamCoef(Layer)(index) = 0.0;
   13739          42 :                     state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsBeamBackCoef(Layer)(index) = 0.0;
   13740             :                 }
   13741             :             }
   13742             :         }
   13743           1 :         return (newConstruct);
   13744             :     }
   13745             : 
   13746           8 :     void ModifyWindow(EnergyPlusData &state,
   13747             :                       int const SurfNum,    // SurfNum has construction of glazing system from Window5 Data File;
   13748             :                       bool &ErrorsFound,    // Set to true if errors found
   13749             :                       int &AddedSubSurfaces // Subsurfaces added when window references a
   13750             :     )
   13751             :     {
   13752             : 
   13753             :         // SUBROUTINE INFORMATION:
   13754             :         //       AUTHOR         Fred Winkelmann
   13755             :         //       DATE WRITTEN   Feb 2002
   13756             :         //       MODIFIED       June 2004, FCW: SinAzim, CosAzim, SinTilt, CosTilt, OutNormVec, GrossArea
   13757             :         //                       and Perimeter weren't being set for created window for case when
   13758             :         //                       window from Window5DataFile had two different glazing systems. Also,
   13759             :         //                       GrossArea and Perimeter of original window were not being recalculated.
   13760             :         //                      October 2007, LKL: Net area for shading calculations was not being
   13761             :         //                       recalculated.
   13762             :         //       RE-ENGINEERED  na
   13763             : 
   13764             :         // PURPOSE OF THIS SUBROUTINE:
   13765             :         // If a window from the Window5DataFile has one glazing system, modify the
   13766             :         // vertex coordinates of the original window to correspond to the dimensions
   13767             :         // of the glazing system on the Data File.
   13768             :         // If a window from the Window5DataFile has two different glazing systems, split
   13769             :         // the window into two separate windows with different properties and adjust the
   13770             :         // vertices of these windows taking into account the dimensions of the glazing systems
   13771             :         // on the Data File and the width and orientation of the mullion that separates
   13772             :         // the glazing systems.
   13773             : 
   13774             :         // Using/Aliasing
   13775             : 
   13776             :         using namespace Vectors;
   13777             : 
   13778             :         // Locals
   13779             :         // SUBROUTINE ARGUMENT DEFINITIONS:
   13780             :         // If there is a second glazing systme on the Data File, SurfNum+1
   13781             :         // has the construction of the second glazing system.
   13782             : 
   13783             :         // 2-glazing system Window5 data file entry
   13784             : 
   13785             :         // DERIVED TYPE DEFINITIONS:
   13786             : 
   13787             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   13788             :         Real64 H; // Height and width of original window (m)
   13789             :         Real64 W;
   13790             :         // unused1208  REAL(r64)    :: MulWidth                        ! Mullion width (m)
   13791             :         Real64 h1; // height and width of first glazing system (m)
   13792             :         Real64 w1;
   13793             :         // unused1208  REAL(r64)    :: h2,w2                           ! height and width of second glazing system (m)
   13794             :         // unused1208  type (rectangularwindow) :: NewCoord
   13795             :         int IConst;             // Construction number of first glazing system
   13796             :         int IConst2;            // Construction number of second glazing system
   13797          16 :         std::string Const2Name; // Name of construction of second glazing system
   13798             :         // unused1208  REAL(r64)    :: AreaNew                         ! Sum of areas of the two glazing systems (m2)
   13799             : 
   13800           8 :         struct rectangularwindow
   13801             :         {
   13802             :             // Members
   13803             :             Array1D<Vector> Vertex;
   13804             : 
   13805             :             // Default Constructor
   13806           8 :             rectangularwindow() : Vertex(4)
   13807             :             {
   13808           8 :             }
   13809             :         };
   13810             : 
   13811             :         // Object Data
   13812          16 :         Vector TVect;
   13813          16 :         rectangularwindow OriginalCoord;
   13814             : 
   13815           8 :         IConst = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
   13816             : 
   13817             :         // Height and width of original window
   13818           8 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
   13819           8 :         W = VecLength(TVect); // SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
   13820           8 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
   13821           8 :         H = VecLength(TVect); // SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)
   13822             : 
   13823             :         // Save coordinates of original window in case Window 5 data overwrites.
   13824           8 :         OriginalCoord.Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides}) =
   13825          16 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides});
   13826             : 
   13827             :         // Height and width of first glazing system
   13828           8 :         h1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysHeight;
   13829           8 :         w1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysWidth;
   13830             : 
   13831           8 :         Const2Name = state.dataConstruction->Construct(IConst).Name + ":2";
   13832           8 :         IConst2 = UtilityRoutines::FindItemInList(Const2Name, state.dataConstruction->Construct);
   13833             : 
   13834           8 :         if (IConst2 == 0) { // Only one glazing system on Window5 Data File for this window.
   13835             : 
   13836             :             // So... original dimensions and area of window are used (entered in IDF)
   13837             :             // Warning if dimensions of original window differ from those on Data File by more than 10%
   13838             : 
   13839           8 :             if (std::abs((H - h1) / H) > 0.10 || std::abs((W - w1) / W) > 0.10) {
   13840             : 
   13841           8 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   13842           0 :                     ShowWarningError(state,
   13843           0 :                                      "SurfaceGeometry: ModifyWindow: Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
   13844           0 :                                          " uses the Window5 Data File Construction " + state.dataConstruction->Construct(IConst).Name);
   13845           0 :                     ShowContinueError(state, format("The height {:.3R}(m) or width  (m) of this window differs by more than 10%{:.3R}", H, W));
   13846           0 :                     ShowContinueError(state,
   13847           0 :                                       format("from the corresponding height {:.3R} (m) or width  (m) on the Window5 Data file.{:.3R}", h1, w1));
   13848           0 :                     ShowContinueError(state, "This will affect the frame heat transfer calculation if the frame in the Data File entry");
   13849           0 :                     ShowContinueError(state, "is not uniform, i.e., has sections with different geometry and/or thermal properties.");
   13850             :                 } else {
   13851           8 :                     ++state.dataSurfaceGeometry->Warning1Count;
   13852             :                 }
   13853             :             }
   13854             : 
   13855             :             // Calculate net area for base surface
   13856           8 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -=
   13857           8 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
   13858           8 :             if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
   13859           0 :                 ShowSevereError(state,
   13860           0 :                                 "Subsurfaces have too much area for base surface=" +
   13861           0 :                                     state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name);
   13862           0 :                 ShowContinueError(state, "Subsurface creating error=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
   13863           0 :                 ErrorsFound = true;
   13864             :             }
   13865             : 
   13866             :             // Net area of base surface with unity window multipliers (used in shadowing checks)
   13867           8 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
   13868           8 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
   13869             : 
   13870             :         } else { // Two glazing systems on Window5 data file for this window
   13871             : 
   13872             :             // if exterior window, okay.
   13873             : 
   13874           0 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
   13875             :                 // There are two glazing systems (separated by a vertical or horizontal mullion) on the Window5 Data File.
   13876             :                 // Fill in geometry data for the second window (corresponding to the second glazing system on the data file.
   13877             :                 // The first glazing system is assumed to be at left for vertical mullion, at bottom for horizontal mullion.
   13878             :                 // The second glazing system is assumed to be at right for vertical mullion, at top for horizontal mullion.
   13879             :                 // The lower left-hand corner of the original window (its vertex #2) is assumed to coincide with
   13880             :                 // vertex #2 of the first glazing system.
   13881             : 
   13882           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   13883           0 :                     ShowMessage(state,
   13884           0 :                                 "SurfaceGeometry: ModifyWindow: Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
   13885           0 :                                     " has been replaced with the Window 5/6 two glazing system=\"" + state.dataConstruction->Construct(IConst).Name +
   13886             :                                     "\".");
   13887           0 :                     ShowContinueError(state, "Note that originally entered dimensions are overridden.");
   13888             :                 } else {
   13889           0 :                     ++state.dataSurfaceGeometry->Warning2Count;
   13890             :                 }
   13891             : 
   13892             :                 // Allocate another window
   13893           0 :                 AddWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
   13894             : 
   13895           0 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond > 0) { // Interior window, specified  ! not external environment
   13896             : 
   13897           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   13898           0 :                     ShowWarningError(state,
   13899           0 :                                      "SurfaceGeometry: ModifyWindow: Interior Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
   13900           0 :                                          " has been replaced with the Window 5/6 two glazing system=\"" +
   13901           0 :                                          state.dataConstruction->Construct(IConst).Name + "\".");
   13902           0 :                     ShowContinueError(
   13903             :                         state, "Please check to make sure interior window is correct. Note that originally entered dimensions are overridden.");
   13904             :                 } else {
   13905           0 :                     ++state.dataSurfaceGeometry->Warning3Count;
   13906             :                 }
   13907             : 
   13908           0 :                 AddWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
   13909             : 
   13910             :             } else { // Interior window, specified not entered
   13911             : 
   13912           0 :                 ShowSevereError(state,
   13913           0 :                                 "SurfaceGeometry: ModifyWindow: Interior Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
   13914             :                                     " is a window in an adjacent zone.");
   13915           0 :                 ShowContinueError(
   13916           0 :                     state, "Attempted to add/reverse Window 5/6 multiple glazing system=\"" + state.dataConstruction->Construct(IConst).Name + "\".");
   13917           0 :                 ShowContinueError(state, "Cannot use these Window 5/6 constructs for these Interior Windows. Program will terminate.");
   13918           0 :                 ErrorsFound = true;
   13919             :             }
   13920             : 
   13921             :         } // End of check if one or two glazing systems are on the Window5 Data File
   13922           8 :     }
   13923             : 
   13924           0 :     void AddWindow(EnergyPlusData &state,
   13925             :                    int const SurfNum,    // SurfNum has construction of glazing system from Window5 Data File;
   13926             :                    bool &ErrorsFound,    // Set to true if errors found
   13927             :                    int &AddedSubSurfaces // Subsurfaces added when window references a
   13928             :     )
   13929             :     {
   13930             : 
   13931             :         // SUBROUTINE INFORMATION:
   13932             :         //       AUTHOR         Linda Lawrie
   13933             :         //       DATE WRITTEN   Nov 2008
   13934             :         //       MODIFIED       na
   13935             :         //       RE-ENGINEERED  na
   13936             : 
   13937             :         // PURPOSE OF THIS SUBROUTINE:
   13938             :         // This routine is called from ModifyWindow to add a window.  Allows it to be
   13939             :         // called in more than one place in the calling routine so as to be able to have
   13940             :         // specific warnings or errors issued.
   13941             : 
   13942             :         // Using/Aliasing
   13943             : 
   13944             :         using namespace Vectors;
   13945             : 
   13946             :         // Locals
   13947             :         // SUBROUTINE ARGUMENT DEFINITIONS:
   13948             :         // If there is a second glazing systme on the Data File, SurfNum+1
   13949             :         // has the construction of the second glazing system.
   13950             : 
   13951             :         // 2-glazing system Window5 data file entry
   13952             : 
   13953             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   13954             :         int loop; // DO loop index
   13955             :         Real64 H; // Height and width of original window (m)
   13956             :         Real64 W;
   13957             :         Real64 MulWidth; // Mullion width (m)
   13958             :         Real64 h1;       // height and width of first glazing system (m)
   13959             :         Real64 w1;
   13960             :         Real64 h2; // height and width of second glazing system (m)
   13961             :         Real64 w2;
   13962             :         Real64 xa; // Vertex intermediate variables (m)
   13963             :         Real64 ya;
   13964             :         Real64 za;
   13965             :         Real64 xb;
   13966             :         Real64 yb;
   13967             :         Real64 zb;
   13968             :         Real64 dx; // Vertex displacements from original window (m)
   13969             :         Real64 dy;
   13970             :         int IConst;             // Construction number of first glazing system
   13971             :         int IConst2;            // Construction number of second glazing system
   13972           0 :         std::string Const2Name; // Name of construction of second glazing system
   13973             :         Real64 AreaNew;         // Sum of areas of the two glazing systems (m2)
   13974             : 
   13975           0 :         struct rectangularwindow
   13976             :         {
   13977             :             // Members
   13978             :             Array1D<Vector> Vertex;
   13979             : 
   13980             :             // Default Constructor
   13981           0 :             rectangularwindow() : Vertex(4)
   13982             :             {
   13983           0 :             }
   13984             :         };
   13985             : 
   13986             :         // Object Data
   13987           0 :         Vector TVect;
   13988           0 :         rectangularwindow NewCoord;
   13989           0 :         rectangularwindow OriginalCoord;
   13990             : 
   13991           0 :         IConst = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
   13992             : 
   13993             :         // Height and width of original window
   13994           0 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
   13995           0 :         W = VecLength(TVect); // SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
   13996           0 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
   13997           0 :         H = VecLength(TVect); // SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)
   13998             : 
   13999             :         // Save coordinates of original window in case Window 5 data overwrites.
   14000           0 :         OriginalCoord.Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides}) =
   14001           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides});
   14002             : 
   14003             :         // Height and width of first glazing system
   14004           0 :         h1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysHeight;
   14005           0 :         w1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysWidth;
   14006             : 
   14007           0 :         Const2Name = state.dataConstruction->Construct(IConst).Name + ":2";
   14008           0 :         IConst2 = UtilityRoutines::FindItemInList(Const2Name, state.dataConstruction->Construct);
   14009             : 
   14010           0 :         ++AddedSubSurfaces;
   14011           0 :         state.dataSurfaceGeometry->SurfaceTmp.redimension(++state.dataSurface->TotSurfaces);
   14012             : 
   14013           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex.allocate(4);
   14014             : 
   14015           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + ":2";
   14016           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Construction = IConst2;
   14017           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ConstructionStoredInputValue = IConst2;
   14018           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Class = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class;
   14019           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
   14020             :         // Sine and cosine of azimuth and tilt
   14021           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SinAzim = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim;
   14022           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).CosAzim = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim;
   14023           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SinTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt;
   14024           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).CosTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt;
   14025             :         // Outward normal unit vector (pointing away from room)
   14026           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Centroid = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Centroid;
   14027           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsx = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx;
   14028           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsy = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy;
   14029           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsz = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz;
   14030           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NewellAreaVector =
   14031           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector;
   14032           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec;
   14033           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Reveal = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Reveal;
   14034           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Shape = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Shape;
   14035           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
   14036           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Tilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
   14037           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ConvOrientation =
   14038           0 :             ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
   14039           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).HeatTransSurf =
   14040           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf;
   14041           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).BaseSurfName =
   14042           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
   14043           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).BaseSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf;
   14044           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName;
   14045           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Zone = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
   14046           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtBoundCondName =
   14047           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName;
   14048           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtBoundCond =
   14049           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond;
   14050           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar;
   14051           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind;
   14052           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorGround =
   14053           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround;
   14054           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorSky =
   14055           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
   14056           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorGroundIR =
   14057           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR;
   14058           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorSkyIR =
   14059           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR;
   14060           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr;
   14061           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SchedShadowSurfIndex =
   14062           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex;
   14063           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).activeWindowShadingControl =
   14064           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl;
   14065           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).windowShadingControlList =
   14066           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
   14067           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).HasShadeControl =
   14068           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl;
   14069           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).activeShadedConstruction =
   14070           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
   14071           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).windowShadingControlList =
   14072           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
   14073           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).shadedStormWinConstructionList =
   14074           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList;
   14075           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).FrameDivider =
   14076           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider;
   14077           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Multiplier = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
   14078           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NetAreaShadowCalc =
   14079           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc;
   14080             : 
   14081           0 :         MulWidth = state.dataConstruction->Construct(IConst).W5FileMullionWidth;
   14082           0 :         w2 = state.dataConstruction->Construct(IConst2).W5FileGlazingSysWidth;
   14083           0 :         h2 = state.dataConstruction->Construct(IConst2).W5FileGlazingSysHeight;
   14084             : 
   14085             :         // Correction to net area of base surface. Add back in the original glazing area and subtract the
   14086             :         // area of the two glazing systems. Note that for Surface(SurfNum)%Class = 'Window' the effect
   14087             :         // of a window multiplier is included in the glazing area. Note that frame areas are subtracted later.
   14088             : 
   14089           0 :         AreaNew = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier * (h1 * w1 + h2 * w2); // both glazing systems
   14090             :         // Adjust net area for base surface
   14091           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -= AreaNew;
   14092             : 
   14093             :         // Net area of base surface with unity window multipliers (used in shadowing checks)
   14094           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
   14095           0 :             AreaNew / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
   14096             : 
   14097             :         // Reset area, etc. of original window
   14098           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier * (h1 * w1);
   14099           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
   14100           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = h1 * w1;
   14101           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = 2 * (h1 + w1);
   14102           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = h1;
   14103           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = w1;
   14104             :         // Set area, etc. of new window
   14105           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Area =
   14106           0 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Multiplier * (h2 * w2);
   14107           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).GrossArea =
   14108           0 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Area;
   14109           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NetAreaShadowCalc = h2 * w2;
   14110           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Perimeter = 2 * (h2 + w2);
   14111           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Height = h2;
   14112           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Width = w2;
   14113             : 
   14114           0 :         if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
   14115           0 :             ShowSevereError(state,
   14116           0 :                             "SurfaceGeometry: ModifyWindow: Subsurfaces have too much area for base surface=" +
   14117           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name);
   14118           0 :             ShowContinueError(state, "Subsurface (window) creating error=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
   14119           0 :             ShowContinueError(state,
   14120           0 :                               format("This window has been replaced by two windows from the Window5 Data File of total area {:.2R} m2", AreaNew));
   14121           0 :             ErrorsFound = true;
   14122             :         }
   14123             : 
   14124             :         // Assign vertices to the new window; modify vertices of original window.
   14125             :         // In the following, vertices are numbered counter-clockwise with vertex #1 at the upper left.
   14126             : 
   14127           0 :         if (state.dataConstruction->Construct(IConst).W5FileMullionOrientation == DataWindowEquivalentLayer::Orientation::Vertical) {
   14128             : 
   14129             :             // VERTICAL MULLION: original window is modified to become left-hand glazing (system #1);
   14130             :             // new window is created to become right-hand glazing (system #2)
   14131             : 
   14132             :             // Left-hand glazing
   14133             : 
   14134             :             // Vertex 1
   14135           0 :             dx = 0.0;
   14136           0 :             dy = H - h1;
   14137           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14138           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14139           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14140           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14141           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14142           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14143           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14144           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14145           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14146             : 
   14147             :             // Vertex 2
   14148           0 :             dx = 0.0;
   14149           0 :             dy = H;
   14150           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14151           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14152           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14153           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14154           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14155           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14156           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14157           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14158           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14159             : 
   14160             :             // Vertex 3
   14161           0 :             dx = w1;
   14162           0 :             dy = H;
   14163           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14164           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14165           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14166           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14167           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14168           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14169           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14170           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14171           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14172             : 
   14173             :             // Vertex 4
   14174           0 :             dx = w1;
   14175           0 :             dy = H - h1;
   14176           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14177           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14178           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14179           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14180           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14181           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14182           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14183           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14184           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14185             : 
   14186           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++loop) {
   14187           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(loop) = NewCoord.Vertex(loop);
   14188             :             }
   14189             : 
   14190             :             // Right-hand glazing
   14191             : 
   14192             :             // Vertex 1
   14193           0 :             dx = w1 + MulWidth;
   14194           0 :             dy = H - (h1 + h2) / 2.0;
   14195           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14196           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14197           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14198           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14199           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14200           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14201           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14202           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14203           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14204             : 
   14205             :             // Vertex 2
   14206           0 :             dx = w1 + MulWidth;
   14207           0 :             dy = H + (h2 - h1) / 2.0;
   14208           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14209           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14210           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14211           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14212           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14213           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14214           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14215           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14216           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14217             : 
   14218             :             // Vertex 3
   14219           0 :             dx = w1 + MulWidth + w2;
   14220           0 :             dy = H + (h2 - h1) / 2.0;
   14221           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14222           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14223           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14224           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14225           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14226           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14227           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14228           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14229           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14230             : 
   14231             :             // Vertex 4
   14232           0 :             dx = w1 + MulWidth + w2;
   14233           0 :             dy = H - (h1 + h2) / 2.0;
   14234           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14235           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14236           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14237           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14238           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14239           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14240           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14241           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14242           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14243             : 
   14244           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides; ++loop) {
   14245           0 :                 state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex(loop) = NewCoord.Vertex(loop);
   14246             :             }
   14247             : 
   14248             :         } else { // Horizontal mullion
   14249             : 
   14250             :             // HORIZONTAL MULLION: original window is modified to become bottom glazing (system #1);
   14251             :             // new window is created to become top glazing (system #2)
   14252             : 
   14253             :             // Bottom glazing
   14254             : 
   14255             :             // Vertex 1
   14256           0 :             dx = 0.0;
   14257           0 :             dy = H - h1;
   14258           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14259           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14260           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14261           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14262           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14263           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14264           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14265           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14266           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14267             : 
   14268             :             // Vertex 2
   14269           0 :             dx = 0.0;
   14270           0 :             dy = H;
   14271           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14272           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14273           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14274           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14275           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14276           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14277           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14278           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14279           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14280             : 
   14281             :             // Vertex 3
   14282           0 :             dx = w1;
   14283           0 :             dy = H;
   14284           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14285           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14286           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14287           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14288           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14289           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14290           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14291           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14292           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14293             : 
   14294             :             // Vertex 4
   14295           0 :             dx = w1;
   14296           0 :             dy = H - h1;
   14297           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14298           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14299           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14300           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14301           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14302           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14303           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14304           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14305           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14306             : 
   14307           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++loop) {
   14308           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(loop) = NewCoord.Vertex(loop);
   14309             :             }
   14310             : 
   14311             :             // Top glazing
   14312             : 
   14313             :             // Vertex 1
   14314           0 :             dx = (w1 - w2) / 2.0;
   14315           0 :             dy = H - (h1 + h2 + MulWidth);
   14316           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14317           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14318           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14319           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14320           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14321           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14322           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14323           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14324           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14325             : 
   14326             :             // Vertex 2
   14327           0 :             dx = (w1 - w2) / 2.0;
   14328           0 :             dy = H - (h1 + MulWidth);
   14329           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14330           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14331           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14332           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14333           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14334           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14335           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14336           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14337           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14338             : 
   14339             :             // Vertex 3
   14340           0 :             dx = (w1 + w2) / 2.0;
   14341           0 :             dy = H - (h1 + MulWidth);
   14342           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14343           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14344           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14345           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14346           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14347           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14348           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14349           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14350           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14351             : 
   14352             :             // Vertex 4
   14353           0 :             dx = (w1 + w2) / 2.0;
   14354           0 :             dy = H - (h1 + h2 + MulWidth);
   14355           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14356           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14357           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14358           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14359           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14360           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14361           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14362           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14363           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14364             : 
   14365           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides; ++loop) {
   14366           0 :                 state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex(loop) = NewCoord.Vertex(loop);
   14367             :             }
   14368             : 
   14369             :         } // End of check if vertical or horizontal mullion
   14370           0 :     }
   14371             : 
   14372       40339 :     void TransformVertsByAspect(EnergyPlusData &state,
   14373             :                                 int const SurfNum, // Current surface number
   14374             :                                 int const NSides   // Number of sides to figure
   14375             :     )
   14376             :     {
   14377             :         // SUBROUTINE INFORMATION:
   14378             :         //       AUTHOR         Brent T Griffith
   14379             :         //       DATE WRITTEN   April 2003
   14380             :         //       MODIFIED       na
   14381             :         //       RE-ENGINEERED  na
   14382             : 
   14383             :         // PURPOSE OF THIS SUBROUTINE:
   14384             :         // Alter input for surface geometry
   14385             :         // Optimizing building design for energy can involve
   14386             :         //  altering building geometry.  Rather than assemble routines to transform
   14387             :         //  geometry through pre-processing on input, it may be simpler to change
   14388             :         //  vertices within EnergyPlus since it already reads the data from the input
   14389             :         //  file and there would no longer be a need to rewrite the text data.
   14390             :         //  This is essentially a crude hack to allow adjusting geometry with
   14391             :         //  a single parameter...
   14392             : 
   14393             :         // METHODOLOGY EMPLOYED:
   14394             :         // once vertices have been converted to WCS, change them to reflect a different aspect
   14395             :         // ratio for the entire building based on user input.
   14396             :         // This routine is called once for each surface by subroutine GetVertices
   14397             : 
   14398       40339 :         static std::string const CurrentModuleObject("GeometryTransform");
   14399             : 
   14400       40387 :         Array1D_string cAlphas(1);
   14401       40387 :         Array1D<Real64> rNumerics(2);
   14402             :         int NAlphas;
   14403             :         int NNum;
   14404             :         int IOStat;
   14405       40339 :         auto &OldAspectRatio = state.dataSurfaceGeometry->OldAspectRatio;
   14406       40339 :         auto &NewAspectRatio = state.dataSurfaceGeometry->NewAspectRatio;
   14407       40339 :         auto &transformPlane = state.dataSurfaceGeometry->transformPlane;
   14408             :         int n;
   14409             :         Real64 Xo;
   14410             :         Real64 XnoRot;
   14411             :         Real64 Xtrans;
   14412             :         Real64 Yo;
   14413             :         Real64 YnoRot;
   14414             :         Real64 Ytrans;
   14415             :         // begin execution
   14416             :         // get user input...
   14417             : 
   14418       40339 :         if (state.dataSurfaceGeometry->firstTime) {
   14419         742 :             if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject) == 1) {
   14420           5 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   14421             :                                                                          CurrentModuleObject,
   14422             :                                                                          1,
   14423             :                                                                          cAlphas,
   14424             :                                                                          NAlphas,
   14425             :                                                                          rNumerics,
   14426             :                                                                          NNum,
   14427             :                                                                          IOStat,
   14428           1 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
   14429           1 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
   14430           1 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
   14431           1 :                                                                          state.dataIPShortCut->cNumericFieldNames);
   14432           1 :                 OldAspectRatio = rNumerics(1);
   14433           1 :                 NewAspectRatio = rNumerics(2);
   14434           1 :                 transformPlane = cAlphas(1);
   14435           1 :                 if (transformPlane != "XY") {
   14436           0 :                     ShowWarningError(
   14437           0 :                         state, CurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + "=\"" + cAlphas(1) + "...ignored.");
   14438             :                 }
   14439           1 :                 state.dataSurfaceGeometry->firstTime = false;
   14440           1 :                 state.dataSurfaceGeometry->noTransform = false;
   14441           1 :                 state.dataSurface->AspectTransform = true;
   14442           1 :                 if (state.dataSurface->WorldCoordSystem) {
   14443           0 :                     ShowWarningError(state, CurrentModuleObject + ": must use Relative Coordinate System.  Transform request ignored.");
   14444           0 :                     state.dataSurfaceGeometry->noTransform = true;
   14445           0 :                     state.dataSurface->AspectTransform = false;
   14446             :                 }
   14447             :             } else {
   14448         741 :                 state.dataSurfaceGeometry->firstTime = false;
   14449             :             }
   14450             :         }
   14451       40339 :         if (state.dataSurfaceGeometry->noTransform) return;
   14452             : 
   14453             :         // check surface type.
   14454          48 :         if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) {
   14455             :             // Site Shading do not get transformed.
   14456           2 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_F) return;
   14457             :         }
   14458             : 
   14459             :         // testing method of transforming  x and y coordinates as follows
   14460             : 
   14461             :         // this works if not rotated wrt north axis ... but if it is, then trouble
   14462             :         // try to first derotate it , transform by aspect and then rotate back.
   14463             : 
   14464         240 :         for (n = 1; n <= NSides; ++n) {
   14465         192 :             Xo = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x; // world coordinates.... shifted by relative north angle...
   14466         192 :             Yo = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
   14467             :             // next derotate the building
   14468         192 :             XnoRot = Xo * state.dataSurfaceGeometry->CosBldgRelNorth + Yo * state.dataSurfaceGeometry->SinBldgRelNorth;
   14469         192 :             YnoRot = Yo * state.dataSurfaceGeometry->CosBldgRelNorth - Xo * state.dataSurfaceGeometry->SinBldgRelNorth;
   14470             :             // translate
   14471         192 :             Xtrans = XnoRot * std::sqrt(NewAspectRatio / OldAspectRatio);
   14472         192 :             Ytrans = YnoRot * std::sqrt(OldAspectRatio / NewAspectRatio);
   14473             :             // rerotate
   14474         192 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
   14475         192 :                 Xtrans * state.dataSurfaceGeometry->CosBldgRelNorth - Ytrans * state.dataSurfaceGeometry->SinBldgRelNorth;
   14476             : 
   14477         192 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
   14478         192 :                 Xtrans * state.dataSurfaceGeometry->SinBldgRelNorth + Ytrans * state.dataSurfaceGeometry->CosBldgRelNorth;
   14479             :         }
   14480             :     }
   14481             : 
   14482         771 :     void CalcSurfaceCentroid(EnergyPlusData &state)
   14483             :     {
   14484             : 
   14485             :         // SUBROUTINE INFORMATION:
   14486             :         //       AUTHOR         B. Griffith
   14487             :         //       DATE WRITTEN   Feb. 2004
   14488             :         //       MODIFIED       na
   14489             :         //       RE-ENGINEERED  na
   14490             : 
   14491             :         // PURPOSE OF THIS SUBROUTINE:
   14492             :         // compute centroid of all the surfaces in the main
   14493             :         // surface structure. Store the vertex coordinates of
   14494             :         // the centroid in the 'SURFACE' derived type.
   14495             : 
   14496             :         // METHODOLOGY EMPLOYED:
   14497             :         // The centroid of triangle is easily computed by averaging the vertices
   14498             :         // The centroid of a quadrilateral is computed by area weighting the centroids
   14499             :         // of two triangles.
   14500             :         // (Algorithm would need to be changed for higher order
   14501             :         // polygons with more than four sides).
   14502             : 
   14503             :         using namespace Vectors;
   14504             : 
   14505         771 :         auto &Triangle1 = state.dataSurfaceGeometry->Triangle1;
   14506         771 :         auto &Triangle2 = state.dataSurfaceGeometry->Triangle2;
   14507         771 :         static Vector const zero_vector(0.0);
   14508        1542 :         Vector centroid;
   14509             : 
   14510         771 :         int negZcount(0); // for warning error in surface centroids
   14511             : 
   14512             :         // loop through all the surfaces
   14513       44533 :         for (int ThisSurf = 1; ThisSurf <= state.dataSurface->TotSurfaces; ++ThisSurf) {
   14514       43762 :             auto &surface(state.dataSurface->Surface(ThisSurf));
   14515             : 
   14516       43762 :             if (surface.Class == SurfaceClass::IntMass) continue;
   14517             : 
   14518       41478 :             auto const &vertex(surface.Vertex);
   14519             : 
   14520       41478 :             if (surface.Sides == 3) { // 3-sided polygon
   14521             : 
   14522         183 :                 centroid = cen(vertex(1), vertex(2), vertex(3));
   14523             : 
   14524       41295 :             } else if (surface.Sides == 4) { // 4-sided polygon
   14525             : 
   14526             :                 // split into 2 3-sided polygons (Triangle 1 and Triangle 2)
   14527       41128 :                 Triangle1(1) = vertex(1);
   14528       41128 :                 Triangle1(2) = vertex(2);
   14529       41128 :                 Triangle1(3) = vertex(3);
   14530       41128 :                 Triangle2(1) = vertex(1);
   14531       41128 :                 Triangle2(2) = vertex(3);
   14532       41128 :                 Triangle2(3) = vertex(4);
   14533             : 
   14534             :                 // get total Area of quad.
   14535       41128 :                 Real64 TotalArea(surface.GrossArea);
   14536       41128 :                 if (TotalArea <= 0.0) {
   14537             :                     // catch a problem....
   14538           0 :                     ShowWarningError(state, "CalcSurfaceCentroid: zero area surface, for surface=" + surface.Name);
   14539           0 :                     continue;
   14540             :                 }
   14541             : 
   14542             :                 // get area fraction of triangles.
   14543       41128 :                 Real64 Tri1Area(AreaPolygon(3, Triangle1) / TotalArea);
   14544       41128 :                 Real64 Tri2Area(AreaPolygon(3, Triangle2) / TotalArea);
   14545             : 
   14546             :                 // check if sum of fractions are slightly greater than 1.0 which is a symptom of the triangles for a non-convex
   14547             :                 // quadralateral using the wrong two triangles
   14548       41128 :                 if ((Tri1Area + Tri2Area) > 1.05) {
   14549             : 
   14550             :                     // if so repeat the process with the other two possible triangles (notice the vertices are in a different order this
   14551             :                     // time) split into 2 3-sided polygons (Triangle 1 and Triangle 2)
   14552          20 :                     Triangle1(1) = vertex(1);
   14553          20 :                     Triangle1(2) = vertex(2);
   14554          20 :                     Triangle1(3) = vertex(4);
   14555          20 :                     Triangle2(1) = vertex(2);
   14556          20 :                     Triangle2(2) = vertex(3);
   14557          20 :                     Triangle2(3) = vertex(4);
   14558             : 
   14559             :                     // get area fraction of triangles.
   14560          20 :                     Real64 AreaTriangle1 = AreaPolygon(3, Triangle1);
   14561          20 :                     Real64 AreaTriangle2 = AreaPolygon(3, Triangle2);
   14562          20 :                     TotalArea = AreaTriangle1 + AreaTriangle2;
   14563          20 :                     Tri1Area = AreaTriangle1 / TotalArea;
   14564          20 :                     Tri2Area = AreaTriangle2 / TotalArea;
   14565             :                 }
   14566             : 
   14567             :                 // get centroid of Triangle 1
   14568       82256 :                 Vector cen1(cen(Triangle1(1), Triangle1(2), Triangle1(3)));
   14569             : 
   14570             :                 // get centroid of Triangle 2
   14571       82256 :                 Vector cen2(cen(Triangle2(1), Triangle2(2), Triangle2(3)));
   14572             : 
   14573             :                 // find area weighted combination of the two centroids (coded to avoid temporary Vectors)
   14574       41128 :                 cen1 *= Tri1Area;
   14575       41128 :                 cen2 *= Tri2Area;
   14576       41128 :                 centroid = cen1;
   14577       41128 :                 centroid += cen2;
   14578             : 
   14579         167 :             } else if (surface.Sides >= 5) { // multi-sided polygon
   14580             :                 // (Maybe triangulate?  For now, use old "z" average method")
   14581             :                 // and X and Y -- straight average
   14582             : 
   14583             :                 //        X1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%x)
   14584             :                 //        X2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%x)
   14585             :                 //        Y1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%y)
   14586             :                 //        Y2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%y)
   14587             :                 //        Z1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%z)
   14588             :                 //        Z2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%z)
   14589             :                 //        Xcm=(X1+X2)/2.0d0
   14590             :                 //        Ycm=(Y1+Y2)/2.0d0
   14591             :                 //        Zcm=(Z1+Z2)/2.0d0
   14592             : 
   14593             :                 // Calc centroid as average of surfaces
   14594         167 :                 centroid = 0.0;
   14595        1691 :                 for (int vert = 1; vert <= surface.Sides; ++vert) {
   14596        1524 :                     centroid += vertex(vert);
   14597             :                 }
   14598         167 :                 centroid /= double(surface.Sides);
   14599             : 
   14600             :             } else {
   14601             : 
   14602           0 :                 if (!surface.Name.empty()) {
   14603           0 :                     ShowWarningError(state, "CalcSurfaceCentroid: caught problem with # of sides, for surface=" + surface.Name);
   14604           0 :                     ShowContinueError(state, format("... number of sides must be >= 3, this surface # sides={}", surface.Sides));
   14605             :                 } else {
   14606           0 :                     ShowWarningError(state, format("CalcSurfaceCentroid: caught problem with # of sides, for surface=#{}", ThisSurf));
   14607           0 :                     ShowContinueError(state,
   14608             :                                       "...surface name is blank. Examine surfaces -- this may be a problem with ill-formed interzone surfaces.");
   14609           0 :                     ShowContinueError(state, format("... number of sides must be >= 3, this surface # sides={}", surface.Sides));
   14610             :                 }
   14611           0 :                 centroid = 0.0;
   14612             :             }
   14613             : 
   14614             :             // store result in the surface structure in DataSurfaces
   14615       41478 :             surface.Centroid = centroid;
   14616             : 
   14617       41478 :             if (centroid.z < 0.0) {
   14618         283 :                 if (surface.ExtWind || surface.ExtBoundCond == ExternalEnvironment) ++negZcount;
   14619             :             }
   14620             : 
   14621             :         } // loop through surfaces
   14622             : 
   14623         771 :         if (negZcount > 0) {
   14624           4 :             ShowWarningError(state, format("CalcSurfaceCentroid: {} Surfaces have the Z coordinate < 0.", negZcount));
   14625           4 :             ShowContinueError(state, "...in any calculations, Wind Speed will be 0.0 for these surfaces.");
   14626          12 :             ShowContinueError(state,
   14627          12 :                               format("...in any calculations, Outside temperatures will be the outside temperature + {:.3R} for these surfaces.",
   14628           8 :                                      state.dataEnvrn->WeatherFileTempModCoeff));
   14629           4 :             ShowContinueError(state, "...that is, these surfaces will have conditions as though at ground level.");
   14630             :         }
   14631         771 :     }
   14632             : 
   14633         771 :     void SetupShadeSurfacesForSolarCalcs(EnergyPlusData &state)
   14634             :     {
   14635             :         // SUBROUTINE INFORMATION:
   14636             :         //       AUTHOR         B. Griffith
   14637             :         //       DATE WRITTEN   Dec. 2008
   14638             :         //       MODIFIED       na
   14639             :         //       RE-ENGINEERED  na
   14640             : 
   14641             :         // PURPOSE OF THIS SUBROUTINE:
   14642             :         // determine if Shading surfaces need full solar calcs because they
   14643             :         // are also used to define geometry of an active solar component.
   14644             :         // Normally, a shading surface is not included in calculations of incident solar, only shading
   14645             : 
   14646             :         // METHODOLOGY EMPLOYED:
   14647             :         // Mine solar renewables input and collect surface names.
   14648             :         // find shading surfaces with names that match those in solar objects.
   14649             :         // setup flags for shading surfaces so that the solar renewables can resuse incident solar calcs
   14650             :         // new solar component models that use shading surfaces will have to extend the code here.
   14651             : 
   14652             :         // Using/Aliasing
   14653             : 
   14654             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   14655        1542 :         Array1D_string TmpCandidateSurfaceNames;
   14656        1542 :         Array1D_string TmpCandidateICSSurfaceNames;
   14657        1542 :         Array1D_string TmpCandidateICSBCTypeNames;
   14658             :         int NumCandidateNames;
   14659             :         int NumOfCollectors;
   14660             :         int NumOfICSUnits;
   14661             :         int NumOfFlatPlateUnits;
   14662             :         int NumPVTs;
   14663             :         int NumPVs;
   14664             :         int SurfNum;
   14665             :         int Found;
   14666             :         int CollectorNum;
   14667             :         int PVTnum;
   14668             :         int PVnum;
   14669             :         int NumAlphas;  // Number of alpha names being passed
   14670             :         int NumNumbers; // Number of numeric parameters being passed
   14671             :         int IOStatus;
   14672         771 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   14673             :         // First collect names of surfaces referenced by active solar components
   14674         771 :         cCurrentModuleObject = "SolarCollector:FlatPlate:Water";
   14675         771 :         NumOfFlatPlateUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   14676         771 :         cCurrentModuleObject = "SolarCollector:FlatPlate:PhotovoltaicThermal";
   14677         771 :         NumPVTs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   14678         771 :         cCurrentModuleObject = "Generator:Photovoltaic";
   14679         771 :         NumPVs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   14680         771 :         cCurrentModuleObject = "SolarCollector:IntegralCollectorStorage";
   14681         771 :         NumOfICSUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   14682             : 
   14683         771 :         NumCandidateNames = NumOfFlatPlateUnits + NumPVTs + NumPVs + NumOfICSUnits;
   14684         771 :         NumOfCollectors = NumOfFlatPlateUnits + NumOfICSUnits;
   14685             : 
   14686         771 :         TmpCandidateSurfaceNames.allocate(NumCandidateNames);
   14687         771 :         TmpCandidateICSSurfaceNames.allocate(NumOfCollectors);
   14688         771 :         TmpCandidateICSBCTypeNames.allocate(NumOfCollectors);
   14689             : 
   14690         771 :         if (NumOfCollectors > 0) {
   14691           3 :             cCurrentModuleObject = "SolarCollector:FlatPlate:Water";
   14692          11 :             for (CollectorNum = 1; CollectorNum <= NumOfFlatPlateUnits; ++CollectorNum) {
   14693             : 
   14694          24 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   14695             :                                                                          cCurrentModuleObject,
   14696             :                                                                          CollectorNum,
   14697           8 :                                                                          state.dataIPShortCut->cAlphaArgs,
   14698             :                                                                          NumAlphas,
   14699           8 :                                                                          state.dataIPShortCut->rNumericArgs,
   14700             :                                                                          NumNumbers,
   14701             :                                                                          IOStatus);
   14702             : 
   14703           8 :                 TmpCandidateSurfaceNames(CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
   14704           8 :                 TmpCandidateICSBCTypeNames(CollectorNum) = "";
   14705             :             }
   14706             :         }
   14707             : 
   14708         771 :         if (NumPVTs > 0) {
   14709           1 :             cCurrentModuleObject = "SolarCollector:FlatPlate:PhotovoltaicThermal";
   14710          11 :             for (PVTnum = 1; PVTnum <= NumPVTs; ++PVTnum) {
   14711             : 
   14712          30 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   14713             :                                                                          cCurrentModuleObject,
   14714             :                                                                          PVTnum,
   14715          10 :                                                                          state.dataIPShortCut->cAlphaArgs,
   14716             :                                                                          NumAlphas,
   14717          10 :                                                                          state.dataIPShortCut->rNumericArgs,
   14718             :                                                                          NumNumbers,
   14719             :                                                                          IOStatus);
   14720             : 
   14721          10 :                 TmpCandidateSurfaceNames(NumOfFlatPlateUnits + PVTnum) = state.dataIPShortCut->cAlphaArgs(2);
   14722             :             }
   14723             :         }
   14724             : 
   14725         771 :         if (NumPVs > 0) {
   14726           6 :             cCurrentModuleObject = "Generator:Photovoltaic";
   14727          54 :             for (PVnum = 1; PVnum <= NumPVs; ++PVnum) {
   14728         144 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   14729             :                                                                          cCurrentModuleObject,
   14730             :                                                                          PVnum,
   14731          48 :                                                                          state.dataIPShortCut->cAlphaArgs,
   14732             :                                                                          NumAlphas,
   14733          48 :                                                                          state.dataIPShortCut->rNumericArgs,
   14734             :                                                                          NumNumbers,
   14735             :                                                                          IOStatus);
   14736          48 :                 TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + PVnum) = state.dataIPShortCut->cAlphaArgs(2);
   14737             :             }
   14738             :         }
   14739             : 
   14740         771 :         if (NumOfICSUnits > 0) {
   14741           1 :             cCurrentModuleObject = "SolarCollector:IntegralCollectorStorage";
   14742           3 :             for (CollectorNum = 1; CollectorNum <= NumOfICSUnits; ++CollectorNum) {
   14743           6 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   14744             :                                                                          cCurrentModuleObject,
   14745             :                                                                          CollectorNum,
   14746           2 :                                                                          state.dataIPShortCut->cAlphaArgs,
   14747             :                                                                          NumAlphas,
   14748           2 :                                                                          state.dataIPShortCut->rNumericArgs,
   14749             :                                                                          NumNumbers,
   14750             :                                                                          IOStatus);
   14751           2 :                 TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + NumPVs + CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
   14752           2 :                 TmpCandidateICSSurfaceNames(NumOfFlatPlateUnits + CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
   14753           2 :                 TmpCandidateICSBCTypeNames(NumOfFlatPlateUnits + CollectorNum) = state.dataIPShortCut->cAlphaArgs(4);
   14754             :             }
   14755             :         }
   14756             : 
   14757             :         // loop through all the surfaces
   14758       44533 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
   14759             : 
   14760       43762 :             Found = UtilityRoutines::FindItemInList(state.dataSurface->Surface(SurfNum).Name, TmpCandidateSurfaceNames, NumCandidateNames);
   14761       43762 :             if (Found > 0) {
   14762          48 :                 if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) { // not BIPV, must be a shading surf with solar device
   14763             :                     // Setup missing values to allow shading surfaces to model incident solar and wind
   14764          16 :                     state.dataSurface->Surface(SurfNum).ExtSolar = true;
   14765          16 :                     state.dataSurface->Surface(SurfNum).ExtWind = true;
   14766          16 :                     state.dataSurface->Surface(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurface->Surface(SurfNum).CosTilt);
   14767             :                 }
   14768             :                 // check if this surface is used for ICS collector mounting and has OthersideCondictionsModel as its
   14769             :                 // boundary condition
   14770          48 :                 if (NumOfICSUnits > 0) {
   14771           6 :                     for (CollectorNum = 1; CollectorNum <= NumOfCollectors; ++CollectorNum) {
   14772          10 :                         if (UtilityRoutines::SameString(state.dataSurface->Surface(SurfNum).Name, TmpCandidateICSSurfaceNames(CollectorNum)) &&
   14773           6 :                             UtilityRoutines::SameString(TmpCandidateICSBCTypeNames(CollectorNum), "OTHERSIDECONDITIONSMODEL")) {
   14774           2 :                             state.dataSurface->SurfIsICS(SurfNum) = true;
   14775           2 :                             state.dataSurface->SurfICSPtr(SurfNum) = CollectorNum;
   14776             :                         }
   14777             :                     }
   14778             :                 }
   14779             : 
   14780             :             } // end of IF (Found > 0) Then
   14781             :         }
   14782         771 :     }
   14783             : 
   14784             :     void
   14785        1542 :     SetupEnclosuresAndAirBoundaries(EnergyPlusData &state,
   14786             :                                     EPVector<DataViewFactorInformation::EnclosureViewFactorInformation> &Enclosures, // Radiant or Solar Enclosures
   14787             :                                     SurfaceGeometry::enclosureType const EnclosureType,                              // Radiant or Solar
   14788             :                                     bool &ErrorsFound)                                                               // Set to true if errors found
   14789             :     {
   14790             :         static constexpr std::string_view RoutineName = "SetupEnclosuresAndAirBoundaries";
   14791        1542 :         bool anyGroupedSpaces = false;
   14792        1542 :         bool radiantSetup = false;
   14793        1542 :         bool solarSetup = false;
   14794        3084 :         std::string RadiantOrSolar = "";
   14795        1542 :         int enclosureNum = 0;
   14796        1542 :         if (EnclosureType == RadiantEnclosures) {
   14797         771 :             radiantSetup = true;
   14798         771 :             RadiantOrSolar = "Radiant";
   14799         771 :             state.dataViewFactor->EnclRadInfo.allocate(state.dataGlobal->numSpaces);
   14800         771 :         } else if (EnclosureType == SolarEnclosures) {
   14801         771 :             solarSetup = true;
   14802         771 :             RadiantOrSolar = "Solar";
   14803         771 :             state.dataViewFactor->EnclSolInfo.allocate(state.dataGlobal->numSpaces);
   14804             :         } else {
   14805           0 :             ShowFatalError(state,
   14806           0 :                            std::string{RoutineName} +
   14807             :                                ": Illegal call to this function. Second argument must be 'RadiantEnclosures' or 'SolarEnclosures'");
   14808             :         }
   14809        1542 :         if (std::any_of(state.dataConstruction->Construct.begin(),
   14810        1542 :                         state.dataConstruction->Construct.end(),
   14811       11697 :                         [](Construction::ConstructionProps const &e) { return e.TypeIsAirBoundary; })) {
   14812           6 :             int errorCount = 0;
   14813         336 :             for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
   14814         330 :                 auto &surf(state.dataSurface->Surface(surfNum));
   14815         330 :                 if (surf.Construction == 0) continue;
   14816         306 :                 auto &constr(state.dataConstruction->Construct(surf.Construction));
   14817         306 :                 if (!constr.TypeIsAirBoundary) continue;
   14818          28 :                 surf.IsAirBoundarySurf = true;
   14819             : 
   14820             :                 // Check for invalid air boundary surfaces - valid only on non-adiabatic interzone surfaces
   14821             :                 // Only check this once during radiant setup, skip for solar setup
   14822          28 :                 if (radiantSetup && (surf.ExtBoundCond <= 0 || surf.ExtBoundCond == surfNum)) {
   14823           0 :                     ErrorsFound = true;
   14824           0 :                     if (!state.dataGlobal->DisplayExtraWarnings) {
   14825           0 :                         ++errorCount;
   14826             :                     } else {
   14827           0 :                         ShowSevereError(state,
   14828           0 :                                         std::string{RoutineName} + ": Surface=\"" + surf.Name +
   14829             :                                             "\" uses Construction:AirBoundary in a non-interzone surface.");
   14830             :                     }
   14831             :                 } else {
   14832             :                     // Process air boundary - set surface properties and set up enclosures
   14833             :                     // Radiant exchange
   14834          28 :                     if (surf.IsAirBoundarySurf) {
   14835             :                         // Boundary is grouped - assign enclosure
   14836          28 :                         state.dataHeatBal->AnyAirBoundary = true;
   14837          28 :                         int thisSideEnclosureNum = 0;
   14838          28 :                         int otherSideEnclosureNum = 0;
   14839          28 :                         if (radiantSetup) {
   14840             :                             // Radiant enclosure setup
   14841          14 :                             constr.IsUsedCTF = false;
   14842          14 :                             surf.HeatTransSurf = false;
   14843          14 :                             surf.HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::AirBoundaryNoHT;
   14844          14 :                             thisSideEnclosureNum = state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum;
   14845          14 :                             otherSideEnclosureNum =
   14846          14 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum;
   14847             :                         } else {
   14848             :                             // Solar enclosure setup
   14849          14 :                             thisSideEnclosureNum = state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum;
   14850          14 :                             otherSideEnclosureNum =
   14851          14 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum;
   14852             :                         }
   14853          28 :                         anyGroupedSpaces = true;
   14854          28 :                         if ((thisSideEnclosureNum == 0) && (otherSideEnclosureNum == 0)) {
   14855             :                             // Neither zone is assigned to an enclosure, so increment the counter and assign to both
   14856           6 :                             ++enclosureNum;
   14857           6 :                             auto &thisEnclosure(Enclosures(enclosureNum));
   14858           6 :                             thisSideEnclosureNum = enclosureNum;
   14859           6 :                             thisEnclosure.Name = format("{} Enclosure {}", RadiantOrSolar, enclosureNum);
   14860           6 :                             thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(surf.spaceNum).Name);
   14861           6 :                             thisEnclosure.spaceNums.push_back(surf.spaceNum);
   14862           6 :                             thisEnclosure.FloorArea += state.dataHeatBal->space(surf.spaceNum).floorArea;
   14863           6 :                             otherSideEnclosureNum = enclosureNum;
   14864           6 :                             int otherSideSpaceNum = state.dataSurface->Surface(surf.ExtBoundCond).spaceNum;
   14865           6 :                             if (otherSideSpaceNum != surf.spaceNum) {
   14866           6 :                                 thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(otherSideSpaceNum).Name);
   14867           6 :                                 thisEnclosure.spaceNums.push_back(otherSideSpaceNum);
   14868           6 :                                 thisEnclosure.FloorArea += state.dataHeatBal->space(otherSideSpaceNum).floorArea;
   14869             :                             }
   14870           6 :                             if (radiantSetup) {
   14871           3 :                                 state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum = thisSideEnclosureNum;
   14872           3 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum =
   14873             :                                     otherSideEnclosureNum;
   14874             :                             } else {
   14875           3 :                                 thisEnclosure.ExtWindowArea += state.dataHeatBal->space(surf.spaceNum).extWindowArea;
   14876           3 :                                 thisEnclosure.TotalSurfArea += state.dataHeatBal->space(surf.spaceNum).totalSurfArea;
   14877           3 :                                 if (otherSideSpaceNum != surf.spaceNum) {
   14878           3 :                                     thisEnclosure.ExtWindowArea += state.dataHeatBal->space(otherSideSpaceNum).extWindowArea;
   14879           3 :                                     thisEnclosure.TotalSurfArea += state.dataHeatBal->space(otherSideSpaceNum).totalSurfArea;
   14880             :                                 }
   14881           3 :                                 state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum = thisSideEnclosureNum;
   14882           3 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum =
   14883             :                                     otherSideEnclosureNum;
   14884           6 :                             }
   14885          22 :                         } else if (thisSideEnclosureNum == 0) {
   14886             :                             // Other side is assigned, so use that one for both
   14887           0 :                             thisSideEnclosureNum = otherSideEnclosureNum;
   14888           0 :                             auto &thisEnclosure(Enclosures(thisSideEnclosureNum));
   14889           0 :                             thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(surf.spaceNum).Name);
   14890           0 :                             thisEnclosure.spaceNums.push_back(surf.spaceNum);
   14891           0 :                             thisEnclosure.FloorArea += state.dataHeatBal->space(surf.spaceNum).floorArea;
   14892           0 :                             if (radiantSetup) {
   14893           0 :                                 state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum = thisSideEnclosureNum;
   14894             :                             } else {
   14895           0 :                                 thisEnclosure.ExtWindowArea += state.dataHeatBal->space(surf.spaceNum).extWindowArea;
   14896           0 :                                 thisEnclosure.TotalSurfArea += state.dataHeatBal->space(surf.spaceNum).totalSurfArea;
   14897           0 :                                 state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum = thisSideEnclosureNum;
   14898             :                             }
   14899          22 :                         } else if (otherSideEnclosureNum == 0) {
   14900             :                             // This side is assigned, so use that one for both
   14901           4 :                             otherSideEnclosureNum = thisSideEnclosureNum;
   14902           4 :                             auto &thisEnclosure(Enclosures(thisSideEnclosureNum));
   14903           4 :                             thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).Name);
   14904           4 :                             thisEnclosure.spaceNums.push_back(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
   14905           4 :                             thisEnclosure.FloorArea += state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).floorArea;
   14906           4 :                             if (radiantSetup) {
   14907           2 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum =
   14908             :                                     otherSideEnclosureNum;
   14909             :                             } else {
   14910           2 :                                 thisEnclosure.ExtWindowArea +=
   14911           2 :                                     state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).extWindowArea;
   14912           2 :                                 thisEnclosure.TotalSurfArea +=
   14913           2 :                                     state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).totalSurfArea;
   14914           2 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum =
   14915             :                                     otherSideEnclosureNum;
   14916             :                             }
   14917          18 :                         } else if (thisSideEnclosureNum != otherSideEnclosureNum) {
   14918             :                             // If both sides are already assigned to an enclosure, then merge the two enclosures
   14919           0 :                             auto &thisEnclosure(Enclosures(thisSideEnclosureNum));
   14920           0 :                             auto &otherEnclosure(Enclosures(otherSideEnclosureNum));
   14921           0 :                             for (const auto &zName : thisEnclosure.spaceNames) {
   14922           0 :                                 otherEnclosure.spaceNames.push_back(zName);
   14923             :                             }
   14924           0 :                             for (const auto &zNum : thisEnclosure.spaceNums) {
   14925           0 :                                 otherEnclosure.spaceNums.push_back(zNum);
   14926           0 :                                 if (radiantSetup) {
   14927           0 :                                     state.dataHeatBal->space(zNum).radiantEnclosureNum = otherSideEnclosureNum;
   14928             :                                 } else {
   14929           0 :                                     state.dataHeatBal->space(zNum).solarEnclosureNum = otherSideEnclosureNum;
   14930             :                                 }
   14931             :                             }
   14932           0 :                             otherEnclosure.FloorArea += thisEnclosure.FloorArea;
   14933           0 :                             otherEnclosure.ExtWindowArea += thisEnclosure.ExtWindowArea;
   14934           0 :                             otherEnclosure.TotalSurfArea += thisEnclosure.TotalSurfArea;
   14935             :                             // Move any enclosures beyond thisEnclosure down one slot - at this point all enclosures are named "Radiant
   14936             :                             // Enclosure N"
   14937           0 :                             for (int enclNum = thisSideEnclosureNum; enclNum < enclosureNum; ++enclNum) {
   14938           0 :                                 std::string saveName = Enclosures(enclNum).Name;
   14939           0 :                                 Enclosures(enclNum) = Enclosures(enclNum + 1);
   14940           0 :                                 Enclosures(enclNum).Name = saveName;
   14941           0 :                                 for (int sNum : Enclosures(enclNum).spaceNums) {
   14942           0 :                                     if (radiantSetup) {
   14943           0 :                                         state.dataHeatBal->space(sNum).radiantEnclosureNum = enclNum;
   14944             :                                     } else {
   14945           0 :                                         state.dataHeatBal->space(sNum).solarEnclosureNum = enclNum;
   14946             :                                     }
   14947             :                                 }
   14948             :                             }
   14949             :                             // Clear the last rad enclosure and reduce the total number of enclosures by 1
   14950           0 :                             Enclosures(enclosureNum).Name.clear();
   14951           0 :                             Enclosures(enclosureNum).spaceNames.clear();
   14952           0 :                             Enclosures(enclosureNum).spaceNums.clear();
   14953           0 :                             Enclosures(enclosureNum).FloorArea = 0;
   14954           0 :                             Enclosures(enclosureNum).ExtWindowArea = 0;
   14955           0 :                             Enclosures(enclosureNum).TotalSurfArea = 0;
   14956           0 :                             enclosureNum -= 1;
   14957             :                         }
   14958             :                     } else {
   14959           0 :                         ErrorsFound = true;
   14960           0 :                         ShowSevereError(state,
   14961           0 :                                         std::string{RoutineName} + ": Surface=" + surf.Name + " uses Construction:AirBoundary with illegal option:");
   14962           0 :                         if (radiantSetup) {
   14963           0 :                             ShowContinueError(state, "Radiant Exchange Method must be either GroupedSpaces or IRTSurface.");
   14964             :                         } else {
   14965           0 :                             ShowContinueError(state, "Solar and Daylighting Method must be either GroupedSpaces or InteriorWindow");
   14966             :                         }
   14967             :                     }
   14968          28 :                     if (solarSetup && constr.TypeIsAirBoundaryMixing) {
   14969             :                         // Set up mixing air boundaries only once, during solar setup
   14970          12 :                         int spaceNum1 = min(surf.spaceNum, state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
   14971          12 :                         int spaceNum2 = max(surf.spaceNum, state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
   14972             :                         // This pair already saved?
   14973          12 :                         bool found = false;
   14974          24 :                         for (auto thisAirBoundaryMixing : state.dataHeatBal->airBoundaryMixing) {
   14975          18 :                             if ((spaceNum1 == thisAirBoundaryMixing.space1) && (spaceNum2 == thisAirBoundaryMixing.space2)) {
   14976           6 :                                 found = true;
   14977           6 :                                 break;
   14978             :                             }
   14979             :                         }
   14980          12 :                         if (!found) {
   14981             :                             // Store the space pairs, schedule, and flow rate to use later to create cross mixing objects
   14982             :                             DataHeatBalance::AirBoundaryMixingSpecs newAirBoundaryMixing;
   14983           6 :                             newAirBoundaryMixing.space1 = spaceNum1;
   14984           6 :                             newAirBoundaryMixing.space2 = spaceNum2;
   14985           6 :                             newAirBoundaryMixing.scheduleIndex = state.dataConstruction->Construct(surf.Construction).AirBoundaryMixingSched;
   14986          12 :                             Real64 mixingVolume = state.dataConstruction->Construct(surf.Construction).AirBoundaryACH *
   14987           6 :                                                   min(state.dataHeatBal->space(spaceNum1).Volume, state.dataHeatBal->space(spaceNum2).Volume) /
   14988           6 :                                                   DataGlobalConstants::SecInHour;
   14989           6 :                             newAirBoundaryMixing.mixingVolumeFlowRate = mixingVolume;
   14990           6 :                             state.dataHeatBal->airBoundaryMixing.push_back(newAirBoundaryMixing);
   14991             :                         }
   14992             :                     }
   14993             :                 }
   14994             :             }
   14995           6 :             if (errorCount > 0) {
   14996           0 :                 ShowSevereError(state, format("{}: {} surfaces use Construction:AirBoundary in non-interzone surfaces.", RoutineName, errorCount));
   14997           0 :                 ShowContinueError(state, "For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;");
   14998             :             }
   14999             :         }
   15000             :         // Check for any spaces defined only by floor surface(s) and group them
   15001       11170 :         for (auto const &zone : state.dataHeatBal->Zone) {
   15002        9628 :             int newEnclosureNum = 0;
   15003       19264 :             for (int const spaceNum : zone.spaceIndexes) {
   15004        9636 :                 int spaceEnclosureNum = 0;
   15005        9636 :                 bool spaceHasOnlyFloors = false;
   15006        9636 :                 if (radiantSetup) {
   15007        4818 :                     spaceEnclosureNum = state.dataHeatBal->space(spaceNum).radiantEnclosureNum;
   15008             :                 } else {
   15009        4818 :                     spaceEnclosureNum = state.dataHeatBal->space(spaceNum).solarEnclosureNum;
   15010             :                 }
   15011        9636 :                 if (spaceEnclosureNum == 0) {
   15012        9620 :                     spaceHasOnlyFloors = true;
   15013        9950 :                     for (int const surfNum : state.dataHeatBal->space(spaceNum).surfaces) {
   15014        9946 :                         if (state.dataSurface->Surface(surfNum).Class == SurfaceClass::IntMass) continue;
   15015        9946 :                         if (state.dataSurface->Surface(surfNum).Class != SurfaceClass::Floor) {
   15016        9616 :                             spaceHasOnlyFloors = false;
   15017        9616 :                             break;
   15018             :                         }
   15019             :                     }
   15020             :                 }
   15021        9636 :                 if (spaceEnclosureNum == 0 && spaceHasOnlyFloors) {
   15022           4 :                     anyGroupedSpaces = true;
   15023           4 :                     if (newEnclosureNum == 0) {
   15024             :                         // Assign one new enclosure for all loose floors in this zone
   15025           2 :                         ++enclosureNum;
   15026           2 :                         newEnclosureNum = enclosureNum;
   15027             :                     }
   15028           4 :                     if (radiantSetup) {
   15029           2 :                         state.dataHeatBal->space(spaceNum).radiantEnclosureNum = enclosureNum;
   15030             :                     } else {
   15031           2 :                         state.dataHeatBal->space(spaceNum).solarEnclosureNum = enclosureNum;
   15032             :                     }
   15033           4 :                     auto &thisEnclosure(Enclosures(enclosureNum));
   15034             :                     // Give this enclosure the zone name and assign this to the zone-remainder space if it exists
   15035           4 :                     thisEnclosure.Name = zone.Name;
   15036           4 :                     thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(spaceNum).Name);
   15037           4 :                     thisEnclosure.spaceNums.push_back(spaceNum);
   15038           4 :                     thisEnclosure.FloorArea = state.dataHeatBal->space(spaceNum).floorArea;
   15039           4 :                     thisEnclosure.ExtWindowArea = state.dataHeatBal->space(spaceNum).extWindowArea;
   15040           4 :                     thisEnclosure.TotalSurfArea = state.dataHeatBal->space(spaceNum).totalSurfArea;
   15041             :                 }
   15042             :             }
   15043             :         }
   15044             : 
   15045        1542 :         if (anyGroupedSpaces) {
   15046             :             // All grouped spaces have been assigned to an enclosure, now assign remaining spaces
   15047          50 :             for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
   15048          44 :                 auto &curSpace = state.dataHeatBal->space(spaceNum);
   15049          44 :                 int spaceEnclosureNum = 0;
   15050          44 :                 if (radiantSetup) {
   15051          22 :                     spaceEnclosureNum = curSpace.radiantEnclosureNum;
   15052             :                 } else {
   15053          22 :                     spaceEnclosureNum = curSpace.solarEnclosureNum;
   15054             :                 }
   15055          44 :                 if (spaceEnclosureNum == 0) {
   15056          24 :                     if (UtilityRoutines::SameString(curSpace.Name, state.dataHeatBal->Zone(curSpace.zoneNum).Name + "-Remainder")) {
   15057             :                         // Search for existing enclosure with same name as the zone
   15058           2 :                         spaceEnclosureNum = UtilityRoutines::FindItemInList(state.dataHeatBal->Zone(curSpace.zoneNum).Name, Enclosures);
   15059             :                     }
   15060          24 :                     if (spaceEnclosureNum == 0) {
   15061             :                         // Otherwise add a new one named for the space
   15062          22 :                         ++enclosureNum;
   15063          22 :                         spaceEnclosureNum = enclosureNum;
   15064          22 :                         Enclosures(spaceEnclosureNum).Name = curSpace.Name;
   15065             :                     }
   15066          24 :                     if (radiantSetup) {
   15067          12 :                         curSpace.radiantEnclosureNum = spaceEnclosureNum;
   15068             :                     } else {
   15069          12 :                         curSpace.solarEnclosureNum = spaceEnclosureNum;
   15070             :                     }
   15071          24 :                     auto &thisEnclosure(Enclosures(spaceEnclosureNum));
   15072          24 :                     thisEnclosure.spaceNames.push_back(curSpace.Name);
   15073          24 :                     thisEnclosure.spaceNums.push_back(spaceNum);
   15074          24 :                     thisEnclosure.FloorArea += curSpace.floorArea;
   15075          24 :                     thisEnclosure.ExtWindowArea += curSpace.extWindowArea;
   15076          24 :                     thisEnclosure.TotalSurfArea += curSpace.totalSurfArea;
   15077             :                 }
   15078             :             }
   15079           6 :             if (radiantSetup) {
   15080           3 :                 state.dataViewFactor->NumOfRadiantEnclosures = enclosureNum;
   15081             :             } else {
   15082           3 :                 state.dataViewFactor->NumOfSolarEnclosures = enclosureNum;
   15083             :             }
   15084             :         } else {
   15085             :             // There are no grouped radiant air boundaries, assign each space to it's own radiant enclosure
   15086       11128 :             for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
   15087        9592 :                 auto &thisEnclosure(Enclosures(spaceNum));
   15088        9592 :                 thisEnclosure.Name = state.dataHeatBal->space(spaceNum).Name;
   15089        9592 :                 thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(spaceNum).Name);
   15090        9592 :                 thisEnclosure.spaceNums.push_back(spaceNum);
   15091        9592 :                 thisEnclosure.FloorArea = state.dataHeatBal->space(spaceNum).floorArea;
   15092        9592 :                 if (radiantSetup) {
   15093        4796 :                     state.dataHeatBal->space(spaceNum).radiantEnclosureNum = spaceNum;
   15094             :                 } else {
   15095        4796 :                     state.dataHeatBal->space(spaceNum).solarEnclosureNum = spaceNum;
   15096        4796 :                     thisEnclosure.ExtWindowArea = state.dataHeatBal->space(spaceNum).extWindowArea;
   15097        4796 :                     thisEnclosure.TotalSurfArea = state.dataHeatBal->space(spaceNum).totalSurfArea;
   15098             :                 }
   15099             :             }
   15100        1536 :             if (radiantSetup) {
   15101         768 :                 state.dataViewFactor->NumOfRadiantEnclosures = state.dataGlobal->numSpaces;
   15102             :             } else {
   15103         768 :                 state.dataViewFactor->NumOfSolarEnclosures = state.dataGlobal->numSpaces;
   15104             :             }
   15105             :         }
   15106        1542 :         if (radiantSetup) {
   15107         771 :             assert(state.dataViewFactor->NumOfRadiantEnclosures <= int(Enclosures.size()));
   15108             :         } else {
   15109         771 :             assert(state.dataViewFactor->NumOfSolarEnclosures <= int(Enclosures.size()));
   15110             :         }
   15111             : 
   15112             :         // TODO MJW: For now, set the max and min enclosure numbers for each zone to be used in CalcInteriorRadExchange with ZoneToResimulate
   15113       11170 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   15114       19264 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   15115        9636 :                 if (state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst == -1) { // initial value
   15116        4814 :                     state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst = state.dataHeatBal->space(spaceNum).radiantEnclosureNum;
   15117             :                 } else {
   15118        4822 :                     state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst =
   15119        4822 :                         min(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst, state.dataHeatBal->space(spaceNum).radiantEnclosureNum);
   15120             :                 }
   15121        9636 :                 state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast =
   15122        9636 :                     max(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast, state.dataHeatBal->space(spaceNum).radiantEnclosureNum);
   15123             :             }
   15124        9628 :             assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst != -1);
   15125        9628 :             assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast != -1);
   15126        9628 :             assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst <= state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast);
   15127             :         }
   15128        1542 :     }
   15129             : 
   15130       40093 :     void CheckConvexity(EnergyPlusData &state,
   15131             :                         int const SurfNum, // Current surface number
   15132             :                         int const NSides   // Number of sides to figure
   15133             :     )
   15134             :     {
   15135             : 
   15136             :         // SUBROUTINE INFORMATION:
   15137             :         //       AUTHOR         Tyler Hoyt
   15138             :         //       DATE WRITTEN   December 2010
   15139             :         //       MODIFIED       CR8752 - incorrect note of non-convex polygons
   15140             :         //       RE-ENGINEERED  na
   15141             : 
   15142             :         // PURPOSE OF THIS SUBROUTINE: This subroutine verifies the convexity of a
   15143             :         // surface that is exposed to the sun in the case that full shading calculations
   15144             :         // are required. The calculation conveniently detects collinear points as well,
   15145             :         // and returns a list of indices that are collinear within the plane of the surface.
   15146             : 
   15147             :         // METHODOLOGY EMPLOYED: First the surface is determined to have dimension 2 in
   15148             :         // either the xy, yz, or xz plane. That plane is selected to do the testing.
   15149             :         // Vectors representing the edges of the polygon and the perpendicular dot product
   15150             :         // between adjacent edges are computed. This allows the turning angle to be determined.
   15151             :         // If the turning angle is greater than pi/2, it turns to the right, and if it is
   15152             :         // less than pi/2, it turns left. The direction of the turn is stored, and if it
   15153             :         // changes as the edges are iterated the surface is not convex. Meanwhile it stores
   15154             :         // the indices of vertices that are collinear and are later removed.
   15155             : 
   15156             :         // REFERENCES:
   15157             :         // http://mathworld.wolfram.com/ConvexPolygon.html
   15158             : 
   15159             :         // Using/Aliasing
   15160             : 
   15161             :         using namespace DataErrorTracking;
   15162             : 
   15163       40093 :         constexpr Real64 TurnThreshold(0.000001); // Sensitivity of convexity test, in radians
   15164             : 
   15165       40093 :         Real64 LastTheta = 0.0;                 // Angle between edge vectors
   15166             :         bool SignFlag;                          // Direction of edge turn : true is right, false is left
   15167       40093 :         bool PrevSignFlag(false);               // Container for the sign of the previous iteration's edge turn
   15168       40093 :         bool PrevSignFlagInitialized(false);    // Whether we picked a PrevSignFlag already or not
   15169       40093 :         auto &X = state.dataSurfaceGeometry->X; // containers for x,y,z vertices of the surface
   15170       40093 :         auto &Y = state.dataSurfaceGeometry->Y;
   15171       40093 :         auto &Z = state.dataSurfaceGeometry->Z;
   15172       40093 :         auto &A = state.dataSurfaceGeometry->A; // containers for convexity test
   15173       40093 :         auto &B = state.dataSurfaceGeometry->B;
   15174       40093 :         auto &VertSize = state.dataSurfaceGeometry->VertSize; // size of X,Y,Z,A,B arrays
   15175             : 
   15176       80186 :         std::vector<int> surfCollinearVerts; // index of vertices to remove, 1-indexed
   15177       40093 :         surfCollinearVerts.reserve(NSides + 2);
   15178             : 
   15179       40093 :         if (state.dataSurfaceGeometry->CheckConvexityFirstTime) {
   15180         737 :             X.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15181         737 :             Y.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15182         737 :             Z.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15183         737 :             A.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15184         737 :             B.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15185         737 :             VertSize = state.dataSurface->MaxVerticesPerSurface;
   15186         737 :             state.dataSurfaceGeometry->CheckConvexityFirstTime = false;
   15187             :         }
   15188             : 
   15189       40093 :         if (NSides > VertSize) {
   15190          30 :             X.deallocate();
   15191          30 :             Y.deallocate();
   15192          30 :             Z.deallocate();
   15193          30 :             A.deallocate();
   15194          30 :             B.deallocate();
   15195          30 :             X.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15196          30 :             Y.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15197          30 :             Z.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15198          30 :             A.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15199          30 :             B.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15200          30 :             VertSize = state.dataSurface->MaxVerticesPerSurface;
   15201             :         }
   15202             : 
   15203       40093 :         auto &surfaceTmp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
   15204       40093 :         auto &vertices = surfaceTmp.Vertex;
   15205             : 
   15206      201160 :         for (int n = 1; n <= NSides; ++n) {
   15207      161067 :             X(n) = vertices(n).x;
   15208      161067 :             Y(n) = vertices(n).y;
   15209      161067 :             Z(n) = vertices(n).z;
   15210             :         }
   15211       40093 :         X(NSides + 1) = vertices(1).x;
   15212       40093 :         Y(NSides + 1) = vertices(1).y;
   15213       40093 :         Z(NSides + 1) = vertices(1).z;
   15214       40093 :         X(NSides + 2) = vertices(2).x;
   15215       40093 :         Y(NSides + 2) = vertices(2).y;
   15216       40093 :         Z(NSides + 2) = vertices(2).z;
   15217             : 
   15218             :         // Determine a suitable plane in which to do the tests
   15219       40093 :         Real64 Det = 0.0;
   15220      201160 :         for (int n = 1; n <= NSides; ++n) {
   15221      161067 :             Det += X(n) * Y(n + 1) - X(n + 1) * Y(n);
   15222             :         }
   15223       40093 :         if (std::abs(Det) > 1.e-4) {
   15224       12926 :             A = X;
   15225       12926 :             B = Y;
   15226             :         } else {
   15227       27167 :             Det = 0.0;
   15228      135741 :             for (int n = 1; n <= NSides; ++n) {
   15229      108574 :                 Det += X(n) * Z(n + 1) - X(n + 1) * Z(n);
   15230             :             }
   15231       27167 :             if (std::abs(Det) > 1.e-4) {
   15232       18298 :                 A = X;
   15233       18298 :                 B = Z;
   15234             :             } else {
   15235        8869 :                 Det = 0.0;
   15236       44279 :                 for (int n = 1; n <= NSides; ++n) {
   15237       35410 :                     Det += Y(n) * Z(n + 1) - Y(n + 1) * Z(n);
   15238             :                 }
   15239        8869 :                 if (std::abs(Det) > 1.e-4) {
   15240        8869 :                     A = Y;
   15241        8869 :                     B = Z;
   15242             :                 } else {
   15243             :                     // This condition should not be reached if the surfaces are guaranteed to be planar already
   15244           0 :                     ShowSevereError(state, "CheckConvexity: Surface=\"" + surfaceTmp.Name + "\" is non-planar.");
   15245           0 :                     ShowContinueError(state, "Coincident Vertices will be removed as possible.");
   15246           0 :                     for (int n = 1; n <= surfaceTmp.Sides; ++n) {
   15247           0 :                         auto const &point(vertices(n));
   15248             :                         static constexpr std::string_view ErrFmt(" ({:8.3F},{:8.3F},{:8.3F})");
   15249           0 :                         ShowContinueError(state, EnergyPlus::format(ErrFmt, point.x, point.y, point.z));
   15250             :                     }
   15251             :                 }
   15252             :             }
   15253             :         }
   15254             : 
   15255      199969 :         for (int n = 1; n <= NSides; ++n) { // perform convexity test in the plane determined above.
   15256             : 
   15257      279826 :             DataVectorTypes::Vector_2d pt0(A(n), B(n));
   15258      279826 :             DataVectorTypes::Vector_2d pt1(A(n + 1), B(n + 1));
   15259      279826 :             DataVectorTypes::Vector_2d pt2(A(n + 2), B(n + 2));
   15260             : 
   15261      279826 :             DataVectorTypes::Vector_2d V1 = pt1 - pt0;
   15262      279826 :             DataVectorTypes::Vector_2d V2 = pt2 - pt1;
   15263             : 
   15264      160043 :             Real64 V1len = V1.length(); // = norm_L2()
   15265      160043 :             Real64 V2len = V2.length();
   15266      160043 :             if (V1len <= 1.e-8 || V2len <= 1.e-8) {
   15267             :                 // At least two points are coincident. Should this happen? GetVertices is supposed to pop these vertices
   15268           0 :                 continue;
   15269             :             }
   15270      160043 :             Real64 CrossProd = V1.cross(V2);
   15271      160043 :             Real64 sinarg = CrossProd / (V1len * V2len);
   15272      160043 :             if (sinarg < -1.0) {
   15273         832 :                 sinarg = -1.0;
   15274      159211 :             } else if (sinarg > 1.0) {
   15275         627 :                 sinarg = 1.0;
   15276             :             }
   15277      160043 :             Real64 Theta = std::asin(sinarg);
   15278      160043 :             if (Theta > TurnThreshold) {
   15279       79129 :                 SignFlag = true;
   15280       80914 :             } else if (Theta < -TurnThreshold) {
   15281       80914 :                 SignFlag = false;
   15282             :             } else { // std::abs(Theta) < TurnThreshold
   15283             :                 // Store the index of the collinear vertex for removal
   15284           0 :                 int colinearIndex = n + 1;
   15285           0 :                 if (colinearIndex > NSides) {
   15286           0 :                     colinearIndex -= NSides;
   15287             :                 }
   15288           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   15289           0 :                     ShowWarningError(
   15290             :                         state,
   15291           0 :                         format("CheckConvexity: Surface=\"{}\", vertex {} is colinear with previous and next.", surfaceTmp.Name, colinearIndex));
   15292             :                 }
   15293           0 :                 ++state.dataErrTracking->TotalCoincidentVertices;
   15294           0 :                 surfCollinearVerts.push_back(colinearIndex);
   15295           0 :                 continue;
   15296             :             }
   15297             : 
   15298      200136 :             if (!PrevSignFlagInitialized) {
   15299       40093 :                 PrevSignFlag = SignFlag;
   15300       40093 :                 LastTheta = Theta;
   15301       40093 :                 PrevSignFlagInitialized = true;
   15302       40093 :                 continue;
   15303             :             }
   15304             : 
   15305      119950 :             if (SignFlag != PrevSignFlag) {
   15306         167 :                 if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal && surfaceTmp.ExtSolar) {
   15307          24 :                     if (state.dataGlobal->DisplayExtraWarnings) {
   15308           0 :                         ShowWarningError(state,
   15309           0 :                                          "CheckConvexity: Zone=\"" + state.dataHeatBal->Zone(surfaceTmp.Zone).Name + "\", Surface=\"" +
   15310           0 :                                              surfaceTmp.Name + "\" is non-convex.");
   15311           0 :                         int Np1 = n + 1;
   15312           0 :                         if (Np1 > NSides) {
   15313           0 :                             Np1 -= NSides;
   15314             :                         }
   15315           0 :                         int Np2 = n + 2;
   15316           0 :                         if (Np2 > NSides) {
   15317           0 :                             Np2 -= NSides;
   15318             :                         }
   15319           0 :                         ShowContinueError(state, format("...vertex {} to vertex {} to vertex {}", n, Np1, Np2));
   15320           0 :                         ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", n, X(n), Y(n), Z(n)));
   15321           0 :                         ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", Np1, X(n + 1), Y(n + 1), Z(n + 1)));
   15322           0 :                         ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", Np2, X(n + 2), Y(n + 2), Z(n + 2)));
   15323             :                         // ShowContinueError(state, format("...theta angle=[{:.6R}]", Theta));
   15324             :                         // ShowContinueError(state, format("...last theta angle=[{:.6R}]", LastTheta));
   15325             :                     }
   15326             :                 }
   15327         167 :                 surfaceTmp.IsConvex = false;
   15328         167 :                 break;
   15329             :             }
   15330      119783 :             PrevSignFlag = SignFlag;
   15331      119783 :             LastTheta = Theta;
   15332             :         }
   15333             : 
   15334             :         // must check to make sure don't remove NSides below 3
   15335       40093 :         int M = surfCollinearVerts.size();
   15336       40093 :         if (M > 0) { // Remove the collinear points determined above
   15337           0 :             if (NSides - M >= 3) {
   15338           0 :                 surfaceTmp.Sides = NSides - M;
   15339           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   15340           0 :                     ShowWarningError(state,
   15341           0 :                                      format("CheckConvexity: Surface=\"{}\" has [{}] collinear points that have been removed.", surfaceTmp.Name, M));
   15342             :                 }
   15343             :             } else { // too many
   15344           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   15345           0 :                     ShowWarningError(state, format("CheckConvexity: Surface=\"{}\" has [{}] collinear points.", surfaceTmp.Name, M));
   15346           0 :                     ShowContinueError(state, "...too many to remove all.  Will leave the surface with 3 sides. But this is now a degenerate surface");
   15347             :                 }
   15348           0 :                 ++state.dataErrTracking->TotalDegenerateSurfaces;
   15349           0 :                 surfaceTmp.Sides = 3; // max(NSides - M, 3) = 3 since NSide - M is < 3;
   15350           0 :                 surfCollinearVerts.resize(NSides - 3);
   15351             :             }
   15352             : 
   15353             :             // remove duplicated points: For that we construct a new array of vertices, only copying indices that aren't in SurfCollinearVerts
   15354             :             // Then we move that array into the original one
   15355           0 :             Array1D<Vector> newVertices;
   15356           0 :             newVertices.allocate(surfaceTmp.Sides);
   15357             : 
   15358           0 :             int n = 0;
   15359           0 :             for (int i = 1; i <= NSides; ++i) {
   15360           0 :                 if (std::find(surfCollinearVerts.cbegin(), surfCollinearVerts.cend(), i) == surfCollinearVerts.cend()) {
   15361           0 :                     newVertices(++n) = vertices(i);
   15362             :                 }
   15363             :             }
   15364           0 :             vertices = std::move(newVertices);
   15365             : 
   15366           0 :             if (state.dataGlobal->DisplayExtraWarnings) {
   15367           0 :                 ShowWarningError(state,
   15368           0 :                                  format("CheckConvexity: Surface=\"{}\": The vertex points has been reprocessed as Sides = {}",
   15369             :                                         surfaceTmp.Name,
   15370           0 :                                         surfaceTmp.Sides));
   15371             :             }
   15372             :         }
   15373       40093 :     }
   15374             : 
   15375       41129 :     bool isRectangle(EnergyPlusData &state, int const ThisSurf // Surface number
   15376             :     )
   15377             :     {
   15378             : 
   15379             :         // SUBROUTINE INFORMATION:
   15380             :         //       AUTHOR         M.J. Witte
   15381             :         //       DATE WRITTEN   October 2015
   15382             : 
   15383             :         // PURPOSE: Check if a 4-sided surface is a rectangle
   15384             : 
   15385             :         using namespace Vectors;
   15386             : 
   15387             :         Real64 Diagonal1; // Length of diagonal of 4-sided figure from vertex 1 to vertex 3 (m)
   15388             :         Real64 Diagonal2; // Length of diagonal of 4-sided figure from vertex 2 to vertex 4 (m)
   15389             :         Real64 DotProd;   // Dot product of two adjacent sides - to test for right angle
   15390       41129 :         Real64 const cos89deg = std::cos(89.0 * DataGlobalConstants::DegToRadians); // tolerance for right angle
   15391       82258 :         Vector Vect32;                                                              // normalized vector from vertex 3 to vertex 2
   15392       82258 :         Vector Vect21;                                                              // normalized vector from vertex 2 to vertex 1
   15393             : 
   15394       41129 :         Diagonal1 = VecLength(state.dataSurface->Surface(ThisSurf).Vertex(1) - state.dataSurface->Surface(ThisSurf).Vertex(3));
   15395       41129 :         Diagonal2 = VecLength(state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(4));
   15396             :         // Test for rectangularity
   15397       41129 :         if (std::abs(Diagonal1 - Diagonal2) < 0.020) { // This tolerance based on coincident vertex tolerance of 0.01
   15398       39744 :             Vect32 = VecNormalize(state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2));
   15399       39744 :             Vect21 = VecNormalize(state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1));
   15400       39744 :             DotProd = dot(Vect32, Vect21);
   15401       39744 :             if (std::abs(DotProd) <= cos89deg) {
   15402       36241 :                 return true;
   15403             :             } else {
   15404        3503 :                 return false;
   15405             :             }
   15406             :         } else {
   15407        1385 :             return false;
   15408             :         }
   15409             :     }
   15410             : 
   15411           1 :     void MakeEquivalentRectangle(EnergyPlusData &state,
   15412             :                                  int const SurfNum, // Surface number
   15413             :                                  bool &ErrorsFound  // Error flag indicator (true if errors found)
   15414             :     )
   15415             :     {
   15416             :         // SUBROUTINE INFORMATION:
   15417             :         //       AUTHOR         R. Zhang, LBNL
   15418             :         //       DATE WRITTEN   September 2016
   15419             :         //       MODIFIED       na
   15420             :         //       RE-ENGINEERED  na
   15421             : 
   15422             :         // PURPOSE OF THIS SUBROUTINE:
   15423             :         // Processing of 4-sided but non-rectangular Window, Door or GlassDoor.
   15424             :         // Calculate the effective height and width of the surface.
   15425             :         //
   15426             :         // METHODOLOGY EMPLOYED:
   15427             :         // Transform the surface into an equivalent rectangular surface with the same area and aspect ratio.
   15428             : 
   15429             :         Real64 BaseCosAzimuth;
   15430             :         Real64 BaseCosTilt;
   15431             :         Real64 BaseSinAzimuth;
   15432             :         Real64 BaseSinTilt;
   15433             :         Real64 SurfWorldAz;
   15434             :         Real64 SurfTilt;
   15435             :         Real64 AspectRatio;  // Aspect ratio
   15436             :         Real64 NumSurfSides; // Number of surface sides
   15437             :         Real64 WidthEff;     // Effective width of the surface
   15438             :         Real64 WidthMax;     // X difference between the vertex on the most left and the one on the most right
   15439             :         Real64 HeightEff;    // Effective height of the surface
   15440             :         Real64 HeightMax;    // Y difference between the lowest and toppest vertices
   15441             :         Real64 Xp;
   15442             :         Real64 Yp;
   15443             :         Real64 Zp;
   15444             :         Real64 XLLC;
   15445             :         Real64 YLLC;
   15446             :         Real64 ZLLC;
   15447             : 
   15448           1 :         if (SurfNum == 0) {
   15449             :             // invalid surface
   15450           0 :             ErrorsFound = true;
   15451           0 :             return;
   15452           1 :         } else if (state.dataSurface->Surface(SurfNum).Sides != 4) {
   15453             :             // the method is designed for 4-sided surface
   15454           0 :             return;
   15455           1 :         } else if (isRectangle(state, SurfNum)) {
   15456             :             // no need to transform
   15457           0 :             return;
   15458             :         }
   15459             : 
   15460           1 :         SurfWorldAz = state.dataSurface->Surface(SurfNum).Azimuth;
   15461           1 :         SurfTilt = state.dataSurface->Surface(SurfNum).Tilt;
   15462           1 :         BaseCosAzimuth = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
   15463           1 :         BaseSinAzimuth = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
   15464           1 :         BaseCosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
   15465           1 :         BaseSinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
   15466           1 :         NumSurfSides = state.dataSurface->Surface(SurfNum).Sides;
   15467             : 
   15468             :         // Calculate WidthMax and HeightMax
   15469           1 :         WidthMax = 0.0;
   15470           1 :         HeightMax = 0.0;
   15471           4 :         for (int i = 1; i < NumSurfSides; ++i) {
   15472           9 :             for (int j = i + 1; j <= NumSurfSides; ++j) {
   15473             : 
   15474           6 :                 Xp = state.dataSurface->Surface(SurfNum).Vertex(j).x - state.dataSurface->Surface(SurfNum).Vertex(i).x;
   15475           6 :                 Yp = state.dataSurface->Surface(SurfNum).Vertex(j).y - state.dataSurface->Surface(SurfNum).Vertex(i).y;
   15476           6 :                 Zp = state.dataSurface->Surface(SurfNum).Vertex(j).z - state.dataSurface->Surface(SurfNum).Vertex(i).z;
   15477             : 
   15478           6 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   15479           6 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   15480           6 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   15481             : 
   15482           6 :                 if (std::abs(XLLC) > WidthMax) WidthMax = std::abs(XLLC);
   15483           6 :                 if (std::abs(YLLC) > WidthMax) HeightMax = std::abs(YLLC);
   15484             :             }
   15485             :         }
   15486             : 
   15487             :         // Perform transformation by calculating WidthEff and HeightEff
   15488           1 :         if ((WidthMax > 0) && (HeightMax > 0)) {
   15489           1 :             AspectRatio = WidthMax / HeightMax;
   15490             :         } else {
   15491           0 :             AspectRatio = 1;
   15492             :         }
   15493           1 :         WidthEff = std::sqrt(state.dataSurface->Surface(SurfNum).Area * AspectRatio);
   15494           1 :         HeightEff = std::sqrt(state.dataSurface->Surface(SurfNum).Area / AspectRatio);
   15495             : 
   15496             :         // Assign the effective width and length to the surface
   15497           1 :         state.dataSurface->Surface(SurfNum).Width = WidthEff;
   15498           1 :         state.dataSurface->Surface(SurfNum).Height = HeightEff;
   15499             :     }
   15500             : 
   15501        8432 :     void CheckForReversedLayers(EnergyPlusData &state,
   15502             :                                 bool &RevLayerDiffs,    // true when differences are discovered in interzone constructions
   15503             :                                 int const ConstrNum,    // construction index
   15504             :                                 int const ConstrNumRev, // construction index for reversed construction
   15505             :                                 int const TotalLayers   // total layers for construction definition
   15506             :     )
   15507             :     {
   15508             : 
   15509        8432 :         RevLayerDiffs = false;
   15510             : 
   15511       26277 :         for (int LayerNo = 1; LayerNo <= TotalLayers; ++LayerNo) {
   15512       17847 :             auto &thisConstLayer(state.dataConstruction->Construct(ConstrNum).LayerPoint(LayerNo));
   15513       17847 :             auto &revConstLayer(state.dataConstruction->Construct(ConstrNumRev).LayerPoint(TotalLayers - LayerNo + 1));
   15514       17847 :             auto &thisMatLay(state.dataMaterial->Material(thisConstLayer));
   15515       17847 :             auto &revMatLay(state.dataMaterial->Material(revConstLayer));
   15516       35692 :             if ((thisConstLayer != revConstLayer) ||                                 // Not pointing to the same layer
   15517       35683 :                 (thisMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass) || // Not window glass or glass equivalent layer which have
   15518       35676 :                 (revMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass) ||  // to have certain properties flipped from front to back
   15519       35676 :                 (thisMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer) ||
   15520       17838 :                 (revMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer)) {
   15521             :                 // If not point to the same layer, check to see if this is window glass which might need to have
   15522             :                 // front and back material properties reversed.
   15523           9 :                 Real64 constexpr SmallDiff = 0.0001;
   15524          16 :                 if ((thisMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass) &&
   15525           7 :                     (revMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass)) {
   15526             :                     // Both layers are window glass, so need to check to see if the properties are reversed
   15527          28 :                     if ((abs(thisMatLay.Thickness - revMatLay.Thickness) > SmallDiff) ||
   15528          14 :                         (abs(thisMatLay.ReflectSolBeamBack - revMatLay.ReflectSolBeamFront) > SmallDiff) ||
   15529          14 :                         (abs(thisMatLay.ReflectSolBeamFront - revMatLay.ReflectSolBeamBack) > SmallDiff) ||
   15530          14 :                         (abs(thisMatLay.TransVis - revMatLay.TransVis) > SmallDiff) ||
   15531          14 :                         (abs(thisMatLay.ReflectVisBeamBack - revMatLay.ReflectVisBeamFront) > SmallDiff) ||
   15532          14 :                         (abs(thisMatLay.ReflectVisBeamFront - revMatLay.ReflectVisBeamBack) > SmallDiff) ||
   15533          14 :                         (abs(thisMatLay.TransThermal - revMatLay.TransThermal) > SmallDiff) ||
   15534          14 :                         (abs(thisMatLay.AbsorpThermalBack - revMatLay.AbsorpThermalFront) > SmallDiff) ||
   15535          14 :                         (abs(thisMatLay.AbsorpThermalFront - revMatLay.AbsorpThermalBack) > SmallDiff) ||
   15536          14 :                         (abs(thisMatLay.Conductivity - revMatLay.Conductivity) > SmallDiff) ||
   15537          14 :                         (abs(thisMatLay.GlassTransDirtFactor - revMatLay.GlassTransDirtFactor) > SmallDiff) ||
   15538          14 :                         (thisMatLay.SolarDiffusing != revMatLay.SolarDiffusing) ||
   15539          21 :                         (abs(thisMatLay.YoungModulus - revMatLay.YoungModulus) > SmallDiff) ||
   15540           7 :                         (abs(thisMatLay.PoissonsRatio - revMatLay.PoissonsRatio) > SmallDiff)) {
   15541           0 :                         RevLayerDiffs = true;
   15542           0 :                         break; // exit when diff
   15543             :                     }          // If none of the above conditions is met, then these should be the same layers in reverse (RevLayersDiffs = false)
   15544           2 :                 } else if ((thisMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer) &&
   15545           0 :                            (revMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer)) {
   15546           0 :                     if ((abs(thisMatLay.TausBackBeamBeam - revMatLay.TausFrontBeamBeam) > SmallDiff) ||
   15547           0 :                         (abs(thisMatLay.TausFrontBeamBeam - revMatLay.TausBackBeamBeam) > SmallDiff) ||
   15548           0 :                         (abs(thisMatLay.ReflBackBeamBeam - revMatLay.ReflFrontBeamBeam) > SmallDiff) ||
   15549           0 :                         (abs(thisMatLay.ReflFrontBeamBeam - revMatLay.ReflBackBeamBeam) > SmallDiff) ||
   15550           0 :                         (abs(thisMatLay.TausBackBeamBeamVis - revMatLay.TausFrontBeamBeamVis) > SmallDiff) ||
   15551           0 :                         (abs(thisMatLay.TausFrontBeamBeamVis - revMatLay.TausBackBeamBeamVis) > SmallDiff) ||
   15552           0 :                         (abs(thisMatLay.ReflBackBeamBeamVis - revMatLay.ReflFrontBeamBeamVis) > SmallDiff) ||
   15553           0 :                         (abs(thisMatLay.ReflFrontBeamBeamVis - revMatLay.ReflBackBeamBeamVis) > SmallDiff) ||
   15554           0 :                         (abs(thisMatLay.TausBackBeamDiff - revMatLay.TausFrontBeamDiff) > SmallDiff) ||
   15555           0 :                         (abs(thisMatLay.TausFrontBeamDiff - revMatLay.TausBackBeamDiff) > SmallDiff) ||
   15556           0 :                         (abs(thisMatLay.ReflBackBeamDiff - revMatLay.ReflFrontBeamDiff) > SmallDiff) ||
   15557           0 :                         (abs(thisMatLay.ReflFrontBeamDiff - revMatLay.ReflBackBeamDiff) > SmallDiff) ||
   15558           0 :                         (abs(thisMatLay.TausBackBeamDiffVis - revMatLay.TausFrontBeamDiffVis) > SmallDiff) ||
   15559           0 :                         (abs(thisMatLay.TausFrontBeamDiffVis - revMatLay.TausBackBeamDiffVis) > SmallDiff) ||
   15560           0 :                         (abs(thisMatLay.ReflBackBeamDiffVis - revMatLay.ReflFrontBeamDiffVis) > SmallDiff) ||
   15561           0 :                         (abs(thisMatLay.ReflFrontBeamDiffVis - revMatLay.ReflBackBeamDiffVis) > SmallDiff) ||
   15562           0 :                         (abs(thisMatLay.TausDiffDiff - revMatLay.TausDiffDiff) > SmallDiff) ||
   15563           0 :                         (abs(thisMatLay.ReflBackDiffDiff - revMatLay.ReflFrontDiffDiff) > SmallDiff) ||
   15564           0 :                         (abs(thisMatLay.ReflFrontDiffDiff - revMatLay.ReflBackDiffDiff) > SmallDiff) ||
   15565           0 :                         (abs(thisMatLay.TausDiffDiffVis - revMatLay.TausDiffDiffVis) > SmallDiff) ||
   15566           0 :                         (abs(thisMatLay.ReflBackDiffDiffVis - revMatLay.ReflFrontDiffDiffVis) > SmallDiff) ||
   15567           0 :                         (abs(thisMatLay.ReflFrontDiffDiffVis - revMatLay.ReflBackDiffDiffVis) > SmallDiff) ||
   15568           0 :                         (abs(thisMatLay.TausThermal - revMatLay.TausThermal) > SmallDiff) ||
   15569           0 :                         (abs(thisMatLay.EmissThermalBack - revMatLay.EmissThermalFront) > SmallDiff) ||
   15570           0 :                         (abs(thisMatLay.EmissThermalFront - revMatLay.EmissThermalBack) > SmallDiff) ||
   15571           0 :                         (abs(thisMatLay.Resistance - revMatLay.Resistance) > SmallDiff)) {
   15572           0 :                         RevLayerDiffs = true;
   15573           0 :                         break; // exit when diff
   15574             :                     }          // If none of the above conditions is met, then these should be the same layers in reverse (RevLayersDiffs = false)
   15575             :                 } else {
   15576             :                     // Other material types do not have reversed constructions so if they are not the same layer there is a problem
   15577             :                     // (RevLayersDiffs = true)
   15578           2 :                     RevLayerDiffs = true;
   15579           2 :                     break; // exit when diff
   15580             :                 }          // End check of whether or not these are WindowGlass
   15581             :             }              // else: thisConstLayer is the same as revConstLayer--so there is no problem (RevLayersDiffs = false)
   15582             :         }
   15583        8432 :     }
   15584             : 
   15585             : } // namespace SurfaceGeometry
   15586             : 
   15587        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13