LCOV - code coverage report
Current view: top level - EnergyPlus - SurfaceGeometry.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 5749 9353 61.5 %
Date: 2024-08-24 18:31:18 Functions: 94 99 94.9 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <algorithm>
      50             : #include <cassert>
      51             : #include <cmath>
      52             : #include <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/DataSystemVariables.hh>
      72             : #include <EnergyPlus/DataViewFactorInformation.hh>
      73             : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
      74             : #include <EnergyPlus/DataZoneEquipment.hh>
      75             : #include <EnergyPlus/DaylightingManager.hh>
      76             : #include <EnergyPlus/DisplayRoutines.hh>
      77             : #include <EnergyPlus/EMSManager.hh>
      78             : #include <EnergyPlus/General.hh>
      79             : #include <EnergyPlus/GlobalNames.hh>
      80             : #include <EnergyPlus/HeatBalanceManager.hh>
      81             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      82             : #include <EnergyPlus/Material.hh>
      83             : #include <EnergyPlus/NodeInputManager.hh>
      84             : #include <EnergyPlus/OutAirNodeManager.hh>
      85             : #include <EnergyPlus/OutputProcessor.hh>
      86             : #include <EnergyPlus/OutputReportPredefined.hh>
      87             : #include <EnergyPlus/ScheduleManager.hh>
      88             : #include <EnergyPlus/SolarShading.hh>
      89             : #include <EnergyPlus/SurfaceGeometry.hh>
      90             : #include <EnergyPlus/UtilityRoutines.hh>
      91             : #include <EnergyPlus/Vectors.hh>
      92             : #include <EnergyPlus/WeatherManager.hh>
      93             : #include <EnergyPlus/WindowManager.hh>
      94             : #include <EnergyPlus/ZoneEquipmentManager.hh>
      95             : 
      96             : namespace EnergyPlus {
      97             : 
      98             : namespace SurfaceGeometry {
      99             : 
     100             :     // Module containing the routines dealing with the Surface Geometry
     101             : 
     102             :     // MODULE INFORMATION:
     103             :     //       AUTHOR         Linda Lawrie
     104             :     //       DATE WRITTEN   June 2000
     105             :     //       MODIFIED       DJS (PSU Dec 2006) to add ecoroof
     106             :     //       RE-ENGINEERED  na
     107             : 
     108             :     // PURPOSE OF THIS MODULE:
     109             :     // This module performs the functions required of the surface geometry.
     110             : 
     111             :     using namespace DataEnvironment;
     112             :     using namespace DataHeatBalance;
     113             :     using namespace DataSurfaces;
     114             :     using DataWindowEquivalentLayer::CFSMAXNL;
     115             : 
     116             :     static std::string const BlankString;
     117             : 
     118             :     int constexpr UnenteredAdjacentZoneSurface = -998; // allows users to enter one zone surface ("Zone")
     119             :                                                        // referencing another in adjacent zone
     120             :     int constexpr UnreconciledZoneSurface = -999;      // interim value between entering surfaces ("Surface") and reconciling
     121             : 
     122         796 :     void AllocateSurfaceWindows(EnergyPlusData &state, int NumSurfaces)
     123             :     {
     124         796 :         state.dataSurface->SurfWinA.dimension(state.dataSurface->TotSurfaces, CFSMAXNL + 1, 0.0);
     125         796 :         state.dataSurface->SurfWinADiffFront.dimension(state.dataSurface->TotSurfaces, CFSMAXNL + 1, 0.0);
     126         796 :         state.dataSurface->SurfWinACFOverlap.dimension(state.dataSurface->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
     127             : 
     128         796 :         state.dataSurface->SurfWinFrameQRadOutAbs.dimension(NumSurfaces, 0);
     129         796 :         state.dataSurface->SurfWinFrameQRadInAbs.dimension(NumSurfaces, 0);
     130         796 :         state.dataSurface->SurfWinDividerQRadOutAbs.dimension(NumSurfaces, 0);
     131         796 :         state.dataSurface->SurfWinDividerQRadInAbs.dimension(NumSurfaces, 0);
     132         796 :         state.dataSurface->SurfWinExtBeamAbsByShade.dimension(NumSurfaces, 0);
     133         796 :         state.dataSurface->SurfWinExtDiffAbsByShade.dimension(NumSurfaces, 0);
     134         796 :         state.dataSurface->SurfWinIntBeamAbsByShade.dimension(NumSurfaces, 0);
     135         796 :         state.dataSurface->SurfWinIntSWAbsByShade.dimension(NumSurfaces, 0);
     136         796 :         state.dataSurface->SurfWinInitialDifSolAbsByShade.dimension(NumSurfaces, 0);
     137         796 :         state.dataSurface->SurfWinIntLWAbsByShade.dimension(NumSurfaces, 0);
     138         796 :         state.dataSurface->SurfWinConvHeatFlowNatural.dimension(NumSurfaces, 0);
     139         796 :         state.dataSurface->SurfWinConvHeatGainToZoneAir.dimension(NumSurfaces, 0);
     140         796 :         state.dataSurface->SurfWinRetHeatGainToZoneAir.dimension(NumSurfaces, 0);
     141         796 :         state.dataSurface->SurfWinDividerHeatGain.dimension(NumSurfaces, 0);
     142         796 :         state.dataSurface->SurfWinBlTsolBmBm.dimension(NumSurfaces, 0);
     143         796 :         state.dataSurface->SurfWinBlTsolBmDif.dimension(NumSurfaces, 0);
     144         796 :         state.dataSurface->SurfWinBlTsolDifDif.dimension(NumSurfaces, 0);
     145         796 :         state.dataSurface->SurfWinBlGlSysTsolBmBm.dimension(NumSurfaces, 0);
     146         796 :         state.dataSurface->SurfWinBlGlSysTsolDifDif.dimension(NumSurfaces, 0);
     147         796 :         state.dataSurface->SurfWinScTsolBmBm.dimension(NumSurfaces, 0);
     148         796 :         state.dataSurface->SurfWinScTsolBmDif.dimension(NumSurfaces, 0);
     149         796 :         state.dataSurface->SurfWinScTsolDifDif.dimension(NumSurfaces, 0);
     150         796 :         state.dataSurface->SurfWinScGlSysTsolBmBm.dimension(NumSurfaces, 0);
     151         796 :         state.dataSurface->SurfWinScGlSysTsolDifDif.dimension(NumSurfaces, 0);
     152         796 :         state.dataSurface->SurfWinGlTsolBmBm.dimension(NumSurfaces, 0);
     153         796 :         state.dataSurface->SurfWinGlTsolBmDif.dimension(NumSurfaces, 0);
     154         796 :         state.dataSurface->SurfWinGlTsolDifDif.dimension(NumSurfaces, 0);
     155         796 :         state.dataSurface->SurfWinBmSolTransThruIntWinRep.dimension(NumSurfaces, 0);
     156         796 :         state.dataSurface->SurfWinBmSolAbsdOutsReveal.dimension(NumSurfaces, 0);
     157         796 :         state.dataSurface->SurfWinBmSolRefldOutsRevealReport.dimension(NumSurfaces, 0);
     158         796 :         state.dataSurface->SurfWinBmSolAbsdInsReveal.dimension(NumSurfaces, 0);
     159         796 :         state.dataSurface->SurfWinBmSolRefldInsReveal.dimension(NumSurfaces, 0);
     160         796 :         state.dataSurface->SurfWinBmSolRefldInsRevealReport.dimension(NumSurfaces, 0);
     161         796 :         state.dataSurface->SurfWinOutsRevealDiffOntoGlazing.dimension(NumSurfaces, 0);
     162         796 :         state.dataSurface->SurfWinInsRevealDiffOntoGlazing.dimension(NumSurfaces, 0);
     163         796 :         state.dataSurface->SurfWinInsRevealDiffIntoZone.dimension(NumSurfaces, 0);
     164         796 :         state.dataSurface->SurfWinOutsRevealDiffOntoFrame.dimension(NumSurfaces, 0);
     165         796 :         state.dataSurface->SurfWinInsRevealDiffOntoFrame.dimension(NumSurfaces, 0);
     166         796 :         state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport.dimension(NumSurfaces, 0);
     167         796 :         state.dataSurface->SurfWinInsRevealDiffIntoZoneReport.dimension(NumSurfaces, 0);
     168         796 :         state.dataSurface->SurfWinInsRevealDiffOntoFrameReport.dimension(NumSurfaces, 0);
     169         796 :         state.dataSurface->SurfWinBmSolAbsdInsRevealReport.dimension(NumSurfaces, 0);
     170         796 :         state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy.dimension(NumSurfaces, 0);
     171         796 :         state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy.dimension(NumSurfaces, 0);
     172         796 :         state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy.dimension(NumSurfaces, 0);
     173         796 :         state.dataSurface->SurfWinProfileAngHor.dimension(NumSurfaces, 0);
     174         796 :         state.dataSurface->SurfWinProfileAngVert.dimension(NumSurfaces, 0);
     175             : 
     176         796 :         state.dataSurface->SurfWinShadingFlag.dimension(NumSurfaces, WinShadingType::ShadeOff);
     177         796 :         state.dataSurface->SurfWinShadingFlagEMSOn.dimension(NumSurfaces, 0);
     178         796 :         state.dataSurface->SurfWinShadingFlagEMSValue.dimension(NumSurfaces, 0.0);
     179         796 :         state.dataSurface->SurfWinStormWinFlag.dimension(NumSurfaces, 0);
     180         796 :         state.dataSurface->SurfWinStormWinFlagPrevDay.dimension(NumSurfaces, 0);
     181         796 :         state.dataSurface->SurfWinFracTimeShadingDeviceOn.dimension(NumSurfaces, 0);
     182         796 :         state.dataSurface->SurfWinExtIntShadePrevTS.dimension(NumSurfaces, WinShadingType::ShadeOff);
     183         796 :         state.dataSurface->SurfWinHasShadeOrBlindLayer.dimension(NumSurfaces, 0);
     184         796 :         state.dataSurface->SurfWinSurfDayLightInit.dimension(NumSurfaces, 0);
     185         796 :         state.dataSurface->SurfWinDaylFacPoint.dimension(NumSurfaces, 0);
     186         796 :         state.dataSurface->SurfWinVisTransSelected.dimension(NumSurfaces, 0);
     187         796 :         state.dataSurface->SurfWinSwitchingFactor.dimension(NumSurfaces, 0);
     188         796 :         state.dataSurface->SurfWinVisTransRatio.dimension(NumSurfaces, 0);
     189         796 :         state.dataSurface->SurfWinIRfromParentZone.dimension(NumSurfaces, 0);
     190         796 :         state.dataSurface->SurfWinFrameArea.dimension(NumSurfaces, 0);
     191         796 :         state.dataSurface->SurfWinFrameConductance.dimension(NumSurfaces, 0);
     192         796 :         state.dataSurface->SurfWinFrameSolAbsorp.dimension(NumSurfaces, 0);
     193         796 :         state.dataSurface->SurfWinFrameVisAbsorp.dimension(NumSurfaces, 0);
     194         796 :         state.dataSurface->SurfWinFrameEmis.dimension(NumSurfaces, 0);
     195         796 :         state.dataSurface->SurfWinFrEdgeToCenterGlCondRatio.dimension(NumSurfaces, 1.0);
     196         796 :         state.dataSurface->SurfWinFrameEdgeArea.dimension(NumSurfaces, 0);
     197         796 :         state.dataSurface->SurfWinFrameTempIn.dimension(NumSurfaces, 23.0);
     198         796 :         state.dataSurface->SurfWinFrameTempInOld.dimension(NumSurfaces, 23.0);
     199         796 :         state.dataSurface->SurfWinFrameTempSurfOut.dimension(NumSurfaces, 23.0);
     200         796 :         state.dataSurface->SurfWinProjCorrFrOut.dimension(NumSurfaces, 0);
     201         796 :         state.dataSurface->SurfWinProjCorrFrIn.dimension(NumSurfaces, 0);
     202         796 :         state.dataSurface->SurfWinDividerType.dimension(NumSurfaces, DataSurfaces::FrameDividerType::DividedLite);
     203         796 :         state.dataSurface->SurfWinDividerArea.dimension(NumSurfaces, 0);
     204         796 :         state.dataSurface->SurfWinDividerConductance.dimension(NumSurfaces, 0);
     205         796 :         state.dataSurface->SurfWinDividerSolAbsorp.dimension(NumSurfaces, 0);
     206         796 :         state.dataSurface->SurfWinDividerVisAbsorp.dimension(NumSurfaces, 0);
     207         796 :         state.dataSurface->SurfWinDividerEmis.dimension(NumSurfaces, 0);
     208         796 :         state.dataSurface->SurfWinDivEdgeToCenterGlCondRatio.dimension(NumSurfaces, 1);
     209         796 :         state.dataSurface->SurfWinDividerEdgeArea.dimension(NumSurfaces, 0);
     210         796 :         state.dataSurface->SurfWinDividerTempIn.dimension(NumSurfaces, 23.0);
     211         796 :         state.dataSurface->SurfWinDividerTempInOld.dimension(NumSurfaces, 23.0);
     212         796 :         state.dataSurface->SurfWinDividerTempSurfOut.dimension(NumSurfaces, 23.0);
     213         796 :         state.dataSurface->SurfWinProjCorrDivOut.dimension(NumSurfaces, 0);
     214         796 :         state.dataSurface->SurfWinProjCorrDivIn.dimension(NumSurfaces, 0);
     215         796 :         state.dataSurface->SurfWinShadeAbsFacFace1.dimension(NumSurfaces, 0.5);
     216         796 :         state.dataSurface->SurfWinShadeAbsFacFace2.dimension(NumSurfaces, 0.5);
     217         796 :         state.dataSurface->SurfWinConvCoeffWithShade.dimension(NumSurfaces, 0);
     218         796 :         state.dataSurface->SurfWinOtherConvHeatGain.dimension(NumSurfaces, 0);
     219         796 :         state.dataSurface->SurfWinBlindNumber.dimension(NumSurfaces, 0);
     220         796 :         state.dataSurface->SurfWinEffInsSurfTemp.dimension(NumSurfaces, 23.0);
     221         796 :         state.dataSurface->SurfWinMovableSlats.dimension(NumSurfaces, 0);
     222         796 :         state.dataSurface->SurfWinSlatAngThisTS.dimension(NumSurfaces, 0);
     223         796 :         state.dataSurface->SurfWinSlatAngThisTSDeg.dimension(NumSurfaces, 0);
     224         796 :         state.dataSurface->SurfWinSlatAngThisTSDegEMSon.dimension(NumSurfaces, 0);
     225         796 :         state.dataSurface->SurfWinSlatAngThisTSDegEMSValue.dimension(NumSurfaces, 0);
     226         796 :         state.dataSurface->SurfWinSlatsBlockBeam.dimension(NumSurfaces, 0);
     227         796 :         state.dataSurface->SurfWinSlatsAngIndex.dimension(NumSurfaces, 0);
     228         796 :         state.dataSurface->SurfWinSlatsAngInterpFac.dimension(NumSurfaces, 0);
     229         796 :         state.dataSurface->SurfWinProfileAng.dimension(NumSurfaces, 0);
     230         796 :         state.dataSurface->SurfWinProfAngIndex.dimension(NumSurfaces, 0);
     231         796 :         state.dataSurface->SurfWinProfAngInterpFac.dimension(NumSurfaces, 0);
     232         796 :         state.dataSurface->SurfWinBlindBmBmTrans.dimension(NumSurfaces, 0);
     233         796 :         state.dataSurface->SurfWinBlindAirFlowPermeability.dimension(NumSurfaces, 0);
     234         796 :         state.dataSurface->SurfWinTotGlazingThickness.dimension(NumSurfaces, 0);
     235         796 :         state.dataSurface->SurfWinTanProfileAngHor.dimension(NumSurfaces, 0);
     236         796 :         state.dataSurface->SurfWinTanProfileAngVert.dimension(NumSurfaces, 0);
     237         796 :         state.dataSurface->SurfWinInsideSillDepth.dimension(NumSurfaces, 0);
     238         796 :         state.dataSurface->SurfWinInsideReveal.dimension(NumSurfaces, 0);
     239         796 :         state.dataSurface->SurfWinInsideSillSolAbs.dimension(NumSurfaces, 0);
     240         796 :         state.dataSurface->SurfWinInsideRevealSolAbs.dimension(NumSurfaces, 0);
     241         796 :         state.dataSurface->SurfWinOutsideRevealSolAbs.dimension(NumSurfaces, 0);
     242         796 :         state.dataSurface->SurfWinAirflowSource.dimension(NumSurfaces, DataSurfaces::WindowAirFlowSource::Invalid);
     243         796 :         state.dataSurface->SurfWinAirflowDestination.dimension(NumSurfaces, DataSurfaces::WindowAirFlowDestination::Invalid);
     244         796 :         state.dataSurface->SurfWinAirflowReturnNodePtr.dimension(NumSurfaces, 0);
     245         796 :         state.dataSurface->SurfWinMaxAirflow.dimension(NumSurfaces, 0);
     246         796 :         state.dataSurface->SurfWinAirflowControlType.dimension(NumSurfaces, DataSurfaces::WindowAirFlowControlType::Invalid);
     247         796 :         state.dataSurface->SurfWinAirflowHasSchedule.dimension(NumSurfaces, 0);
     248         796 :         state.dataSurface->SurfWinAirflowSchedulePtr.dimension(NumSurfaces, 0);
     249         796 :         state.dataSurface->SurfWinAirflowThisTS.dimension(NumSurfaces, 0);
     250         796 :         state.dataSurface->SurfWinTAirflowGapOutlet.dimension(NumSurfaces, 0);
     251         796 :         state.dataSurface->SurfWinWindowCalcIterationsRep.dimension(NumSurfaces, 0);
     252         796 :         state.dataSurface->SurfWinVentingOpenFactorMultRep.dimension(NumSurfaces, 0);
     253         796 :         state.dataSurface->SurfWinInsideTempForVentingRep.dimension(NumSurfaces, 0);
     254         796 :         state.dataSurface->SurfWinVentingAvailabilityRep.dimension(NumSurfaces, 0);
     255         796 :         state.dataSurface->SurfWinSkyGndSolarInc.dimension(NumSurfaces, 0);
     256         796 :         state.dataSurface->SurfWinBmGndSolarInc.dimension(NumSurfaces, 0);
     257         796 :         state.dataSurface->SurfWinSolarDiffusing.dimension(NumSurfaces, 0);
     258         796 :         state.dataSurface->SurfWinFrameHeatGain.dimension(NumSurfaces, 0);
     259         796 :         state.dataSurface->SurfWinFrameHeatLoss.dimension(NumSurfaces, 0);
     260         796 :         state.dataSurface->SurfWinDividerHeatLoss.dimension(NumSurfaces, 0);
     261         796 :         state.dataSurface->SurfWinTCLayerTemp.dimension(NumSurfaces, 0);
     262         796 :         state.dataSurface->SurfWinSpecTemp.dimension(NumSurfaces, 0);
     263         796 :         state.dataSurface->SurfWinWindowModelType.dimension(NumSurfaces, WindowModel::Detailed);
     264         796 :         state.dataSurface->SurfWinTDDPipeNum.dimension(NumSurfaces, 0);
     265         796 :         state.dataSurface->SurfWinStormWinConstr.dimension(NumSurfaces, 0);
     266         796 :         state.dataSurface->SurfActiveConstruction.dimension(NumSurfaces, 0);
     267         796 :         state.dataSurface->SurfWinActiveShadedConstruction.dimension(NumSurfaces, 0);
     268         796 :     }
     269             : 
     270         796 :     void SetupZoneGeometry(EnergyPlusData &state, bool &ErrorsFound)
     271             :     {
     272             : 
     273             :         // SUBROUTINE INFORMATION:
     274             :         //       AUTHOR         George Walton
     275             :         //       DATE WRITTEN   September 1977
     276             :         //       MODIFIED       April 2002 (FCW): add warning for Solar Distribution
     277             :         //                      = FullInteriorExterior when window has reveal
     278             :         //                      Add fatal error when triangular window has reveal
     279             :         //                      May 2002(FCW): Allow triangular windows to have reveal (subr SHDRVL
     280             :         //                      in SolarShading). Remove above warning and fatal error.
     281             :         //       RE-ENGINEERED  November 1997 (RKS,LKL)
     282             : 
     283             :         // PURPOSE OF THIS SUBROUTINE:
     284             :         // This subroutine controls the processing of detached shadowing and
     285             :         // zone surfaces for computing their vertices.
     286             : 
     287             :         static constexpr std::string_view RoutineName("SetUpZoneGeometry: ");
     288             : 
     289             :         // Zones must have been "gotten" before this call
     290             :         // The RelNorth variables are used if "relative" coordinates are input as well
     291             :         // as setting up DaylightingCoords
     292             : 
     293             :         // these include building north axis and Building Rotation for Appendix G
     294        1592 :         state.dataSurfaceGeometry->CosBldgRelNorth =
     295         796 :             std::cos(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * Constant::DegToRadians);
     296        1592 :         state.dataSurfaceGeometry->SinBldgRelNorth =
     297         796 :             std::sin(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * Constant::DegToRadians);
     298             : 
     299             :         // these are only for Building Rotation for Appendix G when using world coordinate system
     300         796 :         state.dataSurfaceGeometry->CosBldgRotAppGonly = std::cos(-state.dataHeatBal->BuildingRotationAppendixG * Constant::DegToRadians);
     301         796 :         state.dataSurfaceGeometry->SinBldgRotAppGonly = std::sin(-state.dataHeatBal->BuildingRotationAppendixG * Constant::DegToRadians);
     302             : 
     303         796 :         state.dataSurfaceGeometry->CosZoneRelNorth.allocate(state.dataGlobal->NumOfZones);
     304         796 :         state.dataSurfaceGeometry->SinZoneRelNorth.allocate(state.dataGlobal->NumOfZones);
     305             : 
     306        5852 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     307             : 
     308        5056 :             state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) = std::cos(-state.dataHeatBal->Zone(ZoneNum).RelNorth * Constant::DegToRadians);
     309        5056 :             state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) = std::sin(-state.dataHeatBal->Zone(ZoneNum).RelNorth * Constant::DegToRadians);
     310             :         }
     311         796 :         GetSurfaceData(state, ErrorsFound);
     312             : 
     313         796 :         if (ErrorsFound) {
     314           0 :             state.dataSurfaceGeometry->CosZoneRelNorth.deallocate();
     315           0 :             state.dataSurfaceGeometry->SinZoneRelNorth.deallocate();
     316           0 :             return;
     317             :         }
     318             : 
     319         796 :         ZoneEquipmentManager::GetZoneEquipment(state); // Necessary to get this before window air gap code
     320             : 
     321         796 :         GetWindowGapAirflowControlData(state, ErrorsFound);
     322             : 
     323         796 :         GetStormWindowData(state, ErrorsFound);
     324             : 
     325         796 :         if (!ErrorsFound && state.dataSurface->TotStormWin > 0) CreateStormWindowConstructions(state);
     326             : 
     327         796 :         SetFlagForWindowConstructionWithShadeOrBlindLayer(state);
     328             : 
     329         796 :         state.dataSurfaceGeometry->CosZoneRelNorth.deallocate();
     330         796 :         state.dataSurfaceGeometry->SinZoneRelNorth.deallocate();
     331             : 
     332         796 :         state.dataHeatBal->CalcWindowRevealReflection = false; // Set to True in ProcessSurfaceVertices if beam solar reflection from window reveals
     333             :         // is requested for one or more exterior windows.
     334         796 :         state.dataSurface->BuildingShadingCount = 0;
     335         796 :         state.dataSurface->FixedShadingCount = 0;
     336         796 :         state.dataSurface->AttachedShadingCount = 0;
     337         796 :         state.dataSurface->ShadingSurfaceFirst = 0;
     338         796 :         state.dataSurface->ShadingSurfaceLast = -1;
     339             : 
     340             :         // Reserve space to avoid excess allocations
     341         796 :         state.dataSurface->AllExtSolAndShadingSurfaceList.reserve(state.dataSurface->TotSurfaces);
     342             : 
     343       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { // Loop through all surfaces...
     344       46044 :             auto &thisSurface = state.dataSurface->Surface(SurfNum);
     345             : 
     346       46044 :             state.dataSurface->SurfAirSkyRadSplit(SurfNum) = std::sqrt(0.5 * (1.0 + thisSurface.CosTilt));
     347             : 
     348             :             // Set flag that determines whether a surface is a shadowing surface
     349       46044 :             thisSurface.IsShadowing = false;
     350       46044 :             if (thisSurface.Class == SurfaceClass::Shading || thisSurface.Class == SurfaceClass::Detached_F ||
     351       44450 :                 thisSurface.Class == SurfaceClass::Detached_B) {
     352        1636 :                 thisSurface.IsShadowing = true;
     353        1636 :                 if (state.dataSurface->ShadingSurfaceFirst == 0) state.dataSurface->ShadingSurfaceFirst = SurfNum;
     354        1636 :                 state.dataSurface->ShadingSurfaceLast = SurfNum;
     355             :             }
     356       46044 :             if ((thisSurface.HeatTransSurf && thisSurface.ExtSolar) || thisSurface.IsShadowing) {
     357             :                 // Some attached shading surfaces may be true for both
     358       19332 :                 state.dataSurface->AllExtSolAndShadingSurfaceList.push_back(SurfNum);
     359             :             }
     360       46044 :             if (thisSurface.Class == SurfaceClass::Shading) ++state.dataSurface->AttachedShadingCount;
     361       46044 :             if (thisSurface.Class == SurfaceClass::Detached_F) ++state.dataSurface->FixedShadingCount;
     362       46044 :             if (thisSurface.Class == SurfaceClass::Detached_B) ++state.dataSurface->BuildingShadingCount;
     363             : 
     364       46044 :             if (thisSurface.Class != SurfaceClass::IntMass) ProcessSurfaceVertices(state, SurfNum, ErrorsFound);
     365             :         }
     366             : 
     367        5852 :         for (auto &e : state.dataHeatBal->Zone) {
     368        5056 :             e.ExtWindowArea = 0.0;
     369        5056 :             e.HasWindow = false;
     370        5056 :             e.ExtGrossWallArea = 0.0;
     371        5056 :             e.ExtNetWallArea = 0.0;
     372        5056 :             e.TotalSurfArea = 0.0;
     373         796 :         }
     374             : 
     375        5877 :         for (auto &s : state.dataHeatBal->space) {
     376        5081 :             s.extWindowArea = 0.0;
     377        5081 :             s.totalSurfArea = 0.0;
     378         796 :         }
     379         796 :         bool DetailedWWR = (state.dataInputProcessing->inputProcessor->getNumSectionsFound("DETAILEDWWR_DEBUG") > 0);
     380         796 :         if (DetailedWWR) {
     381           0 :             print(state.files.debug, "{}", "=======User Entered Classification =================");
     382           0 :             print(state.files.debug, "{}", "Surface,Class,Area,Tilt");
     383             :         }
     384             : 
     385       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { // Loop through all surfaces to find windows...
     386       46044 :             auto &thisSurface = state.dataSurface->Surface(SurfNum);
     387             : 
     388       46044 :             if (!thisSurface.HeatTransSurf && !thisSurface.IsAirBoundarySurf) continue; // Skip shadowing (sub)surfaces
     389       44408 :             auto &thisZone = state.dataHeatBal->Zone(thisSurface.Zone);
     390       44408 :             auto &thisSpace = state.dataHeatBal->space(thisSurface.spaceNum);
     391             : 
     392       44408 :             thisZone.TotalSurfArea += thisSurface.Area;
     393       44408 :             thisSpace.totalSurfArea += thisSurface.Area;
     394       44408 :             if (thisSurface.Class == SurfaceClass::Roof) {
     395        5801 :                 thisZone.geometricCeilingArea += thisSurface.GrossArea;
     396       38607 :             } else if (thisSurface.Class == SurfaceClass::Floor) {
     397        6890 :                 thisZone.geometricFloorArea += thisSurface.GrossArea;
     398             :             }
     399       44408 :             if (state.dataConstruction->Construct(thisSurface.Construction).TypeIsWindow) {
     400        6219 :                 thisZone.TotalSurfArea += state.dataSurface->SurfWinFrameArea(SurfNum);
     401        6219 :                 thisZone.HasWindow = true;
     402        6219 :                 thisSpace.totalSurfArea += state.dataSurface->SurfWinFrameArea(SurfNum);
     403        6219 :                 if (((thisSurface.ExtBoundCond == ExternalEnvironment) || (thisSurface.ExtBoundCond == OtherSideCondModeledExt)) &&
     404        6205 :                     (thisSurface.Class != SurfaceClass::TDD_Dome)) {
     405        6203 :                     thisZone.ExtWindowArea += thisSurface.GrossArea;
     406        6203 :                     thisSpace.extWindowArea += thisSurface.GrossArea;
     407        6203 :                     thisZone.ExtWindowArea_Multiplied =
     408        6203 :                         thisZone.ExtWindowArea + thisSurface.GrossArea * thisSurface.Multiplier * thisZone.Multiplier * thisZone.ListMultiplier;
     409        6203 :                     if (DetailedWWR) {
     410           0 :                         print(state.files.debug,
     411             :                               "{},Window,{:.2R},{:.1R}\n",
     412           0 :                               thisSurface.Name,
     413           0 :                               thisSurface.GrossArea * thisSurface.Multiplier * thisZone.Multiplier * thisZone.ListMultiplier,
     414           0 :                               thisSurface.Tilt);
     415             :                     }
     416             :                 }
     417             :             } else {
     418       38189 :                 if (thisSurface.ExtBoundCond == ExternalEnvironment || thisSurface.ExtBoundCond == OtherSideCondModeledExt) {
     419       11649 :                     thisZone.ExteriorTotalSurfArea += thisSurface.GrossArea;
     420       11649 :                     thisSpace.ExteriorTotalSurfArea += thisSurface.GrossArea;
     421       11649 :                     if (thisSurface.Class == SurfaceClass::Wall) {
     422        8906 :                         thisZone.ExtNetWallArea += thisSurface.Area;
     423        8906 :                         thisZone.ExtGrossWallArea += thisSurface.GrossArea;
     424        8906 :                         thisSpace.ExtGrossWallArea += thisSurface.GrossArea;
     425        8906 :                         thisZone.ExtGrossWallArea_Multiplied += thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier;
     426        8906 :                         if (DetailedWWR) {
     427           0 :                             print(state.files.debug,
     428             :                                   "{},Wall,{:.2R},{:.1R}\n",
     429           0 :                                   thisSurface.Name,
     430           0 :                                   thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier,
     431           0 :                                   thisSurface.Tilt);
     432             :                         }
     433             :                     }
     434       26540 :                 } else if (thisSurface.ExtBoundCond == Ground || thisSurface.ExtBoundCond == GroundFCfactorMethod ||
     435       24155 :                            thisSurface.ExtBoundCond == KivaFoundation) {
     436        2423 :                     thisZone.ExteriorTotalGroundSurfArea += thisSurface.GrossArea;
     437        2423 :                     if (thisSurface.Class == SurfaceClass::Wall) {
     438         211 :                         thisZone.ExtGrossGroundWallArea += thisSurface.GrossArea;
     439         211 :                         thisZone.ExtGrossGroundWallArea_Multiplied += thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier;
     440         211 :                         if (DetailedWWR) {
     441           0 :                             print(state.files.debug,
     442             :                                   "{},Wall-GroundContact,{:.2R},{:.1R}\n",
     443           0 :                                   thisSurface.Name,
     444           0 :                                   thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier,
     445           0 :                                   thisSurface.Tilt);
     446             :                         }
     447             :                     }
     448             :                 }
     449             :             }
     450             : 
     451             :         } // ...end of surfaces windows DO loop
     452             : 
     453         796 :         if (DetailedWWR) {
     454           0 :             print(state.files.debug, "{}\n", "========================");
     455           0 :             print(state.files.debug, "{}\n", "Zone,ExtWallArea,ExtWindowArea");
     456             :         }
     457             : 
     458        5852 :         for (auto &thisZone : state.dataHeatBal->Zone) {
     459        5056 :             int CeilCount = 0;
     460        5056 :             int FloorCount = 0;
     461        5056 :             int WallCount = 0;
     462        5056 :             Real64 AverageHeight = 0.0; // Used to keep track of average height of a surface/zone
     463        5056 :             Real64 ZMax = -99999.0;     // Maximum Z of a surface (detailed outside coefficient calculation)
     464        5056 :             Real64 ZMin = 99999.0;      // Minimum Z of a surface (detailed outside coefficient calculation)
     465        5056 :             Real64 ZCeilAvg = 0.0;
     466        5056 :             Real64 ZFlrAvg = 0.0;
     467        5056 :             if (DetailedWWR) {
     468           0 :                 print(state.files.debug, "{},{:.2R},{:.2R}\n", thisZone.Name, thisZone.ExtGrossWallArea, thisZone.ExtWindowArea);
     469             :             }
     470       10124 :             for (int spaceNum : thisZone.spaceIndexes) {
     471        5068 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     472             :                 // Use AllSurfaceFirst which includes air boundaries
     473       49476 :                 for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
     474       44408 :                     auto &thisSurface = state.dataSurface->Surface(SurfNum);
     475             : 
     476       44408 :                     if (thisSurface.Class == SurfaceClass::Roof) {
     477             :                         // Use Average Z for surface, more important for roofs than floors...
     478        5801 :                         ++CeilCount;
     479        5801 :                         Real64 Z1 = minval(thisSurface.Vertex, &Vector::z);
     480        5801 :                         Real64 Z2 = maxval(thisSurface.Vertex, &Vector::z);
     481             :                         //        ZCeilAvg=ZCeilAvg+(Z1+Z2)/2.d0
     482        5801 :                         ZCeilAvg += ((Z1 + Z2) / 2.0) * (thisSurface.GrossArea / thisZone.geometricCeilingArea);
     483             :                     }
     484       44408 :                     if (thisSurface.Class == SurfaceClass::Floor) {
     485             :                         // Use Average Z for surface, more important for roofs than floors...
     486        6890 :                         ++FloorCount;
     487        6890 :                         Real64 Z1 = minval(thisSurface.Vertex, &Vector::z);
     488        6890 :                         Real64 Z2 = maxval(thisSurface.Vertex, &Vector::z);
     489             :                         //        ZFlrAvg=ZFlrAvg+(Z1+Z2)/2.d0
     490        6890 :                         ZFlrAvg += ((Z1 + Z2) / 2.0) * (thisSurface.GrossArea / thisZone.geometricFloorArea);
     491             :                     }
     492       44408 :                     if (thisSurface.Class == SurfaceClass::Wall) {
     493             :                         // Use Wall calculation in case no roof & floor in zone
     494       22621 :                         ++WallCount;
     495       22621 :                         if (WallCount == 1) {
     496        5034 :                             ZMax = thisSurface.Vertex(1).z;
     497        5034 :                             ZMin = ZMax;
     498             :                         }
     499       22621 :                         ZMax = max(ZMax, maxval(thisSurface.Vertex, &Vector::z));
     500       22621 :                         ZMin = min(ZMin, minval(thisSurface.Vertex, &Vector::z));
     501             :                     }
     502             :                 }
     503        5056 :             }
     504        5056 :             if (CeilCount > 0 && FloorCount > 0) {
     505        5053 :                 AverageHeight = ZCeilAvg - ZFlrAvg;
     506             :             } else {
     507           3 :                 AverageHeight = (ZMax - ZMin);
     508             :             }
     509        5056 :             if (AverageHeight <= 0.0) {
     510           0 :                 AverageHeight = (ZMax - ZMin);
     511             :             }
     512             : 
     513        5056 :             if (thisZone.CeilingHeight > 0.0) {
     514        1810 :                 thisZone.ceilingHeightEntered = true;
     515        1810 :                 if (AverageHeight > 0.0) {
     516        1810 :                     if (std::abs(AverageHeight - thisZone.CeilingHeight) / thisZone.CeilingHeight > 0.05) {
     517           8 :                         if (state.dataSurfaceGeometry->ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
     518           0 :                             ShowWarningError(
     519             :                                 state,
     520           0 :                                 format("{}Entered Ceiling Height for some zone(s) significantly different from calculated Ceiling Height",
     521             :                                        RoutineName));
     522           0 :                             ShowContinueError(state,
     523             :                                               "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on each max iteration exceeded.");
     524             :                         }
     525           8 :                         if (state.dataGlobal->DisplayExtraWarnings) {
     526           0 :                             ShowWarningError(state,
     527           0 :                                              format("{}Entered Ceiling Height for Zone=\"{}\" significantly different from calculated Ceiling Height",
     528             :                                                     RoutineName,
     529           0 :                                                     thisZone.Name));
     530             :                             static constexpr std::string_view ValFmt("{:.2F}");
     531           0 :                             std::string String1 = format(ValFmt, thisZone.CeilingHeight);
     532           0 :                             std::string String2 = format(ValFmt, AverageHeight);
     533           0 :                             ShowContinueError(
     534             :                                 state,
     535           0 :                                 format("{}Entered Ceiling Height={}, Calculated Ceiling Height={}, entered height will be used in calculations.",
     536             :                                        RoutineName,
     537             :                                        String1,
     538             :                                        String2));
     539           0 :                         }
     540             :                     }
     541             :                 }
     542             :             }
     543        5056 :             if ((thisZone.CeilingHeight <= 0.0) && (AverageHeight > 0.0)) thisZone.CeilingHeight = AverageHeight;
     544             :             // Need to add check here - don't touch if already user-specified
     545         796 :         }
     546             : 
     547         796 :         CalculateZoneVolume(state); // Calculate Zone Volumes
     548             : 
     549             :         // Calculate zone centroid (and min/max x,y,z for zone)
     550             :         // Use AllSurfaceFirst which includes air boundaries
     551        5852 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     552        5056 :             auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
     553        5056 :             bool nonInternalMassSurfacesPresent = false;
     554        5056 :             bool internalMassSurfacesPresent = false;
     555        5056 :             Real64 TotSurfArea = 0.0;
     556        5056 :             thisZone.Centroid = Vector(0.0, 0.0, 0.0);
     557        5056 :             if ((thisZone.AllSurfaceFirst > 0) && (state.dataSurface->Surface(thisZone.AllSurfaceFirst).Sides > 0)) {
     558        5056 :                 thisZone.MinimumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
     559        5056 :                 thisZone.MaximumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
     560        5056 :                 thisZone.MinimumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
     561        5056 :                 thisZone.MaximumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
     562        5056 :                 thisZone.MinimumZ = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).z;
     563        5056 :                 thisZone.MaximumZ = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).z;
     564             :             }
     565       10124 :             for (int spaceNum : thisZone.spaceIndexes) {
     566        5068 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     567             : 
     568       49476 :                 for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
     569       44408 :                     auto &thisSurface = state.dataSurface->Surface(SurfNum);
     570       44408 :                     if (thisSurface.Class == SurfaceClass::IntMass) {
     571        2398 :                         internalMassSurfacesPresent = true;
     572        2398 :                         continue;
     573             :                     }
     574       42010 :                     if (!thisSurface.IsAirBoundarySurf) nonInternalMassSurfacesPresent = true;
     575       42010 :                     if (thisSurface.Class == SurfaceClass::Wall || (thisSurface.Class == SurfaceClass::Roof) ||
     576       13588 :                         (thisSurface.Class == SurfaceClass::Floor)) {
     577             : 
     578       35312 :                         thisZone.Centroid.x += thisSurface.Centroid.x * thisSurface.GrossArea;
     579       35312 :                         thisZone.Centroid.y += thisSurface.Centroid.y * thisSurface.GrossArea;
     580       35312 :                         thisZone.Centroid.z += thisSurface.Centroid.z * thisSurface.GrossArea;
     581       35312 :                         TotSurfArea += thisSurface.GrossArea;
     582             :                     }
     583       42010 :                     thisZone.MinimumX = min(thisZone.MinimumX, minval(thisSurface.Vertex, &Vector::x));
     584       42010 :                     thisZone.MaximumX = max(thisZone.MaximumX, maxval(thisSurface.Vertex, &Vector::x));
     585       42010 :                     thisZone.MinimumY = min(thisZone.MinimumY, minval(thisSurface.Vertex, &Vector::y));
     586       42010 :                     thisZone.MaximumY = max(thisZone.MaximumY, maxval(thisSurface.Vertex, &Vector::y));
     587       42010 :                     thisZone.MinimumZ = min(thisZone.MinimumZ, minval(thisSurface.Vertex, &Vector::z));
     588       42010 :                     thisZone.MaximumZ = max(thisZone.MaximumZ, maxval(thisSurface.Vertex, &Vector::z));
     589             :                 }
     590        5056 :             }
     591        5056 :             if (TotSurfArea > 0.0) {
     592        5056 :                 thisZone.Centroid.x /= TotSurfArea;
     593        5056 :                 thisZone.Centroid.y /= TotSurfArea;
     594        5056 :                 thisZone.Centroid.z /= TotSurfArea;
     595             :             }
     596        5056 :             if (internalMassSurfacesPresent && !nonInternalMassSurfacesPresent) {
     597           0 :                 ShowSevereError(
     598           0 :                     state, format("{}Zone=\"{}\" has only internal mass surfaces.  Need at least one other surface.", RoutineName, thisZone.Name));
     599           0 :                 ErrorsFound = true;
     600             :             }
     601             :         }
     602             : 
     603         796 :         state.dataSurface->SurfAdjacentZone.dimension(state.dataSurface->TotSurfaces, 0);
     604             :         // note -- adiabatic surfaces will show same zone as surface
     605       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     606       46044 :             if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue;
     607       24098 :             state.dataSurface->SurfAdjacentZone(SurfNum) = state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).ExtBoundCond).Zone;
     608             :         }
     609             : 
     610        5852 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     611     1275666 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     612     1270610 :                 auto &thisSurface = state.dataSurface->Surface(SurfNum);
     613     1270610 :                 if (!thisSurface.HeatTransSurf && thisSurface.ZoneName == state.dataHeatBal->Zone(ZoneNum).Name)
     614        1502 :                     ++state.dataHeatBal->Zone(ZoneNum).NumShadingSurfaces;
     615             : 
     616     1270610 :                 if (thisSurface.Zone != ZoneNum) continue;
     617             : 
     618       44408 :                 if (thisSurface.HeatTransSurf &&
     619       44390 :                     (thisSurface.Class == SurfaceClass::Wall || thisSurface.Class == SurfaceClass::Roof || thisSurface.Class == SurfaceClass::Floor))
     620       35294 :                     ++state.dataHeatBal->Zone(ZoneNum).NumSurfaces;
     621             : 
     622       44408 :                 if (thisSurface.HeatTransSurf && (thisSurface.Class == SurfaceClass::Window || thisSurface.Class == SurfaceClass::GlassDoor ||
     623       38173 :                                                   thisSurface.Class == SurfaceClass::Door || thisSurface.Class == SurfaceClass::TDD_Dome ||
     624       37692 :                                                   thisSurface.Class == SurfaceClass::TDD_Diffuser))
     625        6698 :                     ++state.dataHeatBal->Zone(ZoneNum).NumSubSurfaces;
     626             : 
     627             :             } // surfaces
     628             :         }     // zones
     629             : 
     630       46840 :         for (int const SurfNum : state.dataSurface->AllSurfaceListReportOrder) {
     631       46044 :             auto &thisSurface = state.dataSurface->Surface(SurfNum);
     632       46044 :             bool isWithConvCoefValid = false;
     633       46044 :             Real64 NominalUwithConvCoeffs = 0.0;
     634       46044 :             std::string cNominalUwithConvCoeffs;
     635       46044 :             std::string cNominalU;
     636       46044 :             if (thisSurface.Construction > 0 && thisSurface.Construction <= state.dataHeatBal->TotConstructs) {
     637       44408 :                 NominalUwithConvCoeffs = ComputeNominalUwithConvCoeffs(state, SurfNum, isWithConvCoefValid);
     638       44408 :                 if (isWithConvCoefValid) {
     639       44390 :                     cNominalUwithConvCoeffs = format("{:.3R}", NominalUwithConvCoeffs);
     640             :                 } else {
     641          18 :                     cNominalUwithConvCoeffs = "[invalid]";
     642             :                 }
     643       44408 :                 if ((thisSurface.Class == SurfaceClass::Window) || (thisSurface.Class == SurfaceClass::TDD_Dome)) {
     644             :                     // SurfaceClass::Window also covers glass doors and TDD:Diffusers
     645        6219 :                     cNominalU = "N/A";
     646             :                 } else {
     647       38189 :                     cNominalU = format("{:.3R}", state.dataHeatBal->NominalU(thisSurface.Construction));
     648             :                 }
     649             :             } else {
     650        1636 :                 cNominalUwithConvCoeffs = "**";
     651        1636 :                 cNominalU = "**";
     652             :             }
     653             : 
     654             :             // populate the predefined report related to u-values with films
     655             :             // only exterior surfaces including underground
     656       46044 :             DataSurfaces::SurfaceClass const SurfaceClass(thisSurface.Class);
     657       46044 :             if ((thisSurface.ExtBoundCond == ExternalEnvironment) || (thisSurface.ExtBoundCond == Ground) ||
     658       24408 :                 (thisSurface.ExtBoundCond == KivaFoundation) || (thisSurface.ExtBoundCond == GroundFCfactorMethod)) {
     659       21858 :                 if ((SurfaceClass == SurfaceClass::Wall) || (SurfaceClass == SurfaceClass::Floor) || (SurfaceClass == SurfaceClass::Roof)) {
     660       27236 :                     OutputReportPredefined::PreDefTableEntry(
     661       40854 :                         state, state.dataOutRptPredefined->pdchOpUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     662        8240 :                 } else if (SurfaceClass == SurfaceClass::Door) {
     663         798 :                     OutputReportPredefined::PreDefTableEntry(
     664        1197 :                         state, state.dataOutRptPredefined->pdchDrUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     665             :                 }
     666             :             } else {
     667       24186 :                 if ((SurfaceClass == SurfaceClass::Wall) || (SurfaceClass == SurfaceClass::Floor) || (SurfaceClass == SurfaceClass::Roof)) {
     668       43388 :                     OutputReportPredefined::PreDefTableEntry(
     669       65082 :                         state, state.dataOutRptPredefined->pdchIntOpUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     670        2492 :                 } else if (SurfaceClass == SurfaceClass::Door) {
     671         160 :                     OutputReportPredefined::PreDefTableEntry(
     672         240 :                         state, state.dataOutRptPredefined->pdchIntDrUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
     673             :                 }
     674             :             }
     675       46840 :         } // surfaces
     676             : 
     677             :         // Write number of shadings to initialization output file
     678         796 :         print(state.files.eio,
     679             :               "! <Shading Summary>, Number of Fixed Detached Shades, Number of Building Detached Shades, Number of Attached Shades\n");
     680             : 
     681         796 :         print(state.files.eio,
     682             :               " Shading Summary,{},{},{}\n",
     683         796 :               state.dataSurface->FixedShadingCount,
     684         796 :               state.dataSurface->BuildingShadingCount,
     685         796 :               state.dataSurface->AttachedShadingCount);
     686             : 
     687             :         // Write number of zones header to initialization output file
     688         796 :         print(state.files.eio, "! <Zone Summary>, Number of Zones, Number of Zone Surfaces, Number of SubSurfaces\n");
     689             : 
     690         796 :         print(state.files.eio,
     691             :               " Zone Summary,{},{},{}\n",
     692         796 :               state.dataGlobal->NumOfZones,
     693         796 :               state.dataSurface->TotSurfaces - state.dataSurface->FixedShadingCount - state.dataSurface->BuildingShadingCount -
     694         796 :                   state.dataSurface->AttachedShadingCount,
     695         796 :               sum(state.dataHeatBal->Zone, &ZoneData::NumSubSurfaces));
     696             : 
     697             :         // Write Zone Information header to the initialization output file
     698             :         static constexpr std::string_view Format_721(
     699             :             "! <Zone Information>,Zone Name,North Axis {deg},Origin X-Coordinate {m},Origin Y-Coordinate {m},Origin Z-Coordinate "
     700             :             "{m},Centroid X-Coordinate {m},Centroid Y-Coordinate {m},Centroid Z-Coordinate {m},Type,Zone Multiplier,Zone List "
     701             :             "Multiplier,Minimum X {m},Maximum X {m},Minimum Y {m},Maximum Y {m},Minimum Z {m},Maximum Z {m},Ceiling Height {m},Volume "
     702             :             "{m3},Zone Inside Convection Algorithm {Simple-Detailed-CeilingDiffuser-TrombeWall},Zone Outside Convection Algorithm "
     703             :             "{Simple-Detailed-Tarp-MoWitt-DOE-2-BLAST}, Floor Area {m2},Exterior Gross Wall Area {m2},Exterior Net Wall Area {m2},Exterior "
     704             :             "Window "
     705             :             "Area {m2}, Number of Surfaces, Number of SubSurfaces, Number of Shading SubSurfaces,  Part of Total Building Area");
     706         796 :         print(state.files.eio, "{}\n", Format_721);
     707             : 
     708        5852 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     709             :             // Write Zone Information to the initialization output file
     710        5056 :             std::string String1;
     711        5056 :             std::string String2;
     712        5056 :             std::string String3;
     713             : 
     714        5056 :             switch (state.dataHeatBal->Zone(ZoneNum).IntConvAlgo) {
     715        1094 :             case Convect::HcInt::ASHRAESimple: {
     716        1094 :                 String1 = "Simple";
     717        1094 :             } break;
     718        3936 :             case Convect::HcInt::ASHRAETARP: {
     719        3936 :                 String1 = "TARP";
     720        3936 :             } break;
     721          10 :             case Convect::HcInt::CeilingDiffuser: {
     722          10 :                 String1 = "CeilingDiffuser";
     723          10 :             } break;
     724           1 :             case Convect::HcInt::TrombeWall: {
     725           1 :                 String1 = "TrombeWall";
     726           1 :             } break;
     727          14 :             case Convect::HcInt::AdaptiveConvectionAlgorithm: {
     728          14 :                 String1 = "AdaptiveConvectionAlgorithm";
     729          14 :             } break;
     730           1 :             case Convect::HcInt::ASTMC1340: {
     731           1 :                 String1 = "ASTMC1340";
     732           1 :             } break;
     733           0 :             default:
     734           0 :                 break;
     735             :             }
     736             : 
     737        5056 :             switch (state.dataHeatBal->Zone(ZoneNum).ExtConvAlgo) {
     738        1102 :             case Convect::HcExt::ASHRAESimple: {
     739        1102 :                 String2 = "Simple";
     740        1102 :             } break;
     741         492 :             case Convect::HcExt::ASHRAETARP: {
     742         492 :                 String2 = "TARP";
     743         492 :             } break;
     744           0 :             case Convect::HcExt::TarpHcOutside: {
     745           0 :                 String2 = "TARP";
     746           0 :             } break;
     747           0 :             case Convect::HcExt::MoWiTTHcOutside: {
     748           0 :                 String2 = "MoWitt";
     749           0 :             } break;
     750        3446 :             case Convect::HcExt::DOE2HcOutside: {
     751        3446 :                 String2 = "DOE-2";
     752        3446 :             } break;
     753          16 :             case Convect::HcExt::AdaptiveConvectionAlgorithm: {
     754          16 :                 String2 = "AdaptiveConvectionAlgorithm";
     755          16 :             } break;
     756           0 :             default:
     757           0 :                 break;
     758             :             }
     759             : 
     760        5056 :             String3 = (state.dataHeatBal->Zone(ZoneNum).isPartOfTotalArea) ? "Yes" : "No";
     761             : 
     762             :             static constexpr std::string_view Format_720(
     763             :                 " Zone Information, "
     764             :                 "{},{:.1R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{},{},{},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},"
     765             :                 "{:.2R},{:.2R},{},{},{:.2R},{:.2R},{:.2R},{:.2R},{},{},{},{}\n");
     766             : 
     767        5056 :             print(state.files.eio,
     768             :                   Format_720,
     769        5056 :                   state.dataHeatBal->Zone(ZoneNum).Name,
     770        5056 :                   state.dataHeatBal->Zone(ZoneNum).RelNorth,
     771        5056 :                   state.dataHeatBal->Zone(ZoneNum).OriginX,
     772        5056 :                   state.dataHeatBal->Zone(ZoneNum).OriginY,
     773        5056 :                   state.dataHeatBal->Zone(ZoneNum).OriginZ,
     774        5056 :                   state.dataHeatBal->Zone(ZoneNum).Centroid.x,
     775        5056 :                   state.dataHeatBal->Zone(ZoneNum).Centroid.y,
     776        5056 :                   state.dataHeatBal->Zone(ZoneNum).Centroid.z,
     777        5056 :                   state.dataHeatBal->Zone(ZoneNum).OfType,
     778        5056 :                   state.dataHeatBal->Zone(ZoneNum).Multiplier,
     779        5056 :                   state.dataHeatBal->Zone(ZoneNum).ListMultiplier,
     780        5056 :                   state.dataHeatBal->Zone(ZoneNum).MinimumX,
     781        5056 :                   state.dataHeatBal->Zone(ZoneNum).MaximumX,
     782        5056 :                   state.dataHeatBal->Zone(ZoneNum).MinimumY,
     783        5056 :                   state.dataHeatBal->Zone(ZoneNum).MaximumY,
     784        5056 :                   state.dataHeatBal->Zone(ZoneNum).MinimumZ,
     785        5056 :                   state.dataHeatBal->Zone(ZoneNum).MaximumZ,
     786        5056 :                   state.dataHeatBal->Zone(ZoneNum).CeilingHeight,
     787        5056 :                   state.dataHeatBal->Zone(ZoneNum).Volume,
     788             :                   String1,
     789             :                   String2,
     790        5056 :                   state.dataHeatBal->Zone(ZoneNum).FloorArea,
     791        5056 :                   state.dataHeatBal->Zone(ZoneNum).ExtGrossWallArea,
     792        5056 :                   state.dataHeatBal->Zone(ZoneNum).ExtNetWallArea,
     793        5056 :                   state.dataHeatBal->Zone(ZoneNum).ExtWindowArea,
     794        5056 :                   state.dataHeatBal->Zone(ZoneNum).NumSurfaces,
     795        5056 :                   state.dataHeatBal->Zone(ZoneNum).NumSubSurfaces,
     796        5056 :                   state.dataHeatBal->Zone(ZoneNum).NumShadingSurfaces,
     797             :                   String3);
     798             : 
     799        5056 :         } // ZoneNum
     800             : 
     801             :         // Set up solar distribution enclosures allowing for any air boundaries
     802         796 :         SetupEnclosuresAndAirBoundaries(state, state.dataViewFactor->EnclSolInfo, SurfaceGeometry::enclosureType::SolarEnclosures, ErrorsFound);
     803             : 
     804             :         // Do the Stratosphere check
     805         796 :         SetZoneOutBulbTempAt(state);
     806         796 :         CheckZoneOutBulbTempAt(state);
     807             :     }
     808             : 
     809         796 :     void AllocateSurfaceArrays(EnergyPlusData &state)
     810             :     {
     811             : 
     812             :         // SUBROUTINE INFORMATION:
     813             :         //       AUTHOR         Rick Strand
     814             :         //       DATE WRITTEN   February 1998
     815             :         //       MODIFIED       na
     816             :         //       RE-ENGINEERED  na
     817             : 
     818             :         // PURPOSE OF THIS SUBROUTINE:
     819             :         // This subroutine allocates all of the arrays at the module level which
     820             :         // require allocation.
     821             : 
     822             :         // METHODOLOGY EMPLOYED:
     823             :         // Allocation is dependent on the user input file.
     824             : 
     825             :         // REFERENCES:
     826             :         // na
     827             : 
     828             :         // USE STATEMENTS:
     829             :         // na
     830             : 
     831             :         // SUBROUTINE PARAMETER DEFINITIONS:
     832             :         // na
     833             : 
     834             :         // INTERFACE BLOCK SPECIFICATIONS
     835             :         // na
     836             : 
     837             :         // DERIVED TYPE DEFINITIONS
     838             :         // na
     839             : 
     840             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     841             :         // na
     842         796 :         state.dataSurface->ShadeV.allocate(state.dataSurface->TotSurfaces);
     843       46840 :         for (auto &e : state.dataSurface->ShadeV)
     844       46840 :             e.NVert = 0;
     845             :         // Individual components (XV,YV,ZV) allocated in routine ProcessSurfaceVertices
     846         796 :         state.dataSurface->X0.dimension(state.dataSurface->TotSurfaces, 0.0);
     847         796 :         state.dataSurface->Y0.dimension(state.dataSurface->TotSurfaces, 0.0);
     848         796 :         state.dataSurface->Z0.dimension(state.dataSurface->TotSurfaces, 0.0);
     849             : 
     850             :         // Surface EMS arrays
     851         796 :         state.dataSurface->SurfEMSConstructionOverrideON.allocate(state.dataSurface->TotSurfaces);
     852         796 :         state.dataSurface->SurfEMSConstructionOverrideValue.allocate(state.dataSurface->TotSurfaces);
     853         796 :         state.dataSurface->SurfEMSOverrideIntConvCoef.allocate(state.dataSurface->TotSurfaces);
     854         796 :         state.dataSurface->SurfEMSValueForIntConvCoef.allocate(state.dataSurface->TotSurfaces);
     855         796 :         state.dataSurface->SurfEMSOverrideExtConvCoef.allocate(state.dataSurface->TotSurfaces);
     856         796 :         state.dataSurface->SurfEMSValueForExtConvCoef.allocate(state.dataSurface->TotSurfaces);
     857         796 :         state.dataSurface->SurfOutDryBulbTempEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     858         796 :         state.dataSurface->SurfOutDryBulbTempEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     859         796 :         state.dataSurface->SurfOutWetBulbTempEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     860         796 :         state.dataSurface->SurfOutWetBulbTempEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     861         796 :         state.dataSurface->SurfWindSpeedEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     862         796 :         state.dataSurface->SurfWindSpeedEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     863         796 :         state.dataSurface->SurfViewFactorGroundEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     864         796 :         state.dataSurface->SurfViewFactorGroundEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     865         796 :         state.dataSurface->SurfWindDirEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
     866         796 :         state.dataSurface->SurfWindDirEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
     867       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     868       46044 :             state.dataSurface->SurfEMSConstructionOverrideON(SurfNum) = false;
     869       46044 :             state.dataSurface->SurfEMSConstructionOverrideValue(SurfNum) = 0.0;
     870       46044 :             state.dataSurface->SurfEMSOverrideIntConvCoef(SurfNum) = false;
     871       46044 :             state.dataSurface->SurfEMSValueForIntConvCoef(SurfNum) = 0.0;
     872       46044 :             state.dataSurface->SurfEMSOverrideExtConvCoef(SurfNum) = false;
     873       46044 :             state.dataSurface->SurfEMSValueForExtConvCoef(SurfNum) = 0.0;
     874       46044 :             state.dataSurface->SurfOutDryBulbTempEMSOverrideOn(SurfNum) = false;
     875       46044 :             state.dataSurface->SurfOutDryBulbTempEMSOverrideValue(SurfNum) = 0.0;
     876       46044 :             state.dataSurface->SurfOutWetBulbTempEMSOverrideOn(SurfNum) = false;
     877       46044 :             state.dataSurface->SurfOutWetBulbTempEMSOverrideValue(SurfNum) = 0.0;
     878       46044 :             state.dataSurface->SurfWindSpeedEMSOverrideOn(SurfNum) = false;
     879       46044 :             state.dataSurface->SurfWindSpeedEMSOverrideValue(SurfNum) = 0.0;
     880       46044 :             state.dataSurface->SurfViewFactorGroundEMSOverrideOn(SurfNum) = false;
     881       46044 :             state.dataSurface->SurfViewFactorGroundEMSOverrideValue(SurfNum) = 0.0;
     882       46044 :             state.dataSurface->SurfWindDirEMSOverrideOn(SurfNum) = false;
     883       46044 :             state.dataSurface->SurfWindDirEMSOverrideValue(SurfNum) = 0.0;
     884             :         }
     885             :         // Following are surface hb arrays
     886         796 :         state.dataSurface->SurfOutDryBulbTemp.allocate(state.dataSurface->TotSurfaces);
     887         796 :         state.dataSurface->SurfOutWetBulbTemp.allocate(state.dataSurface->TotSurfaces);
     888         796 :         state.dataSurface->SurfOutWindSpeed.allocate(state.dataSurface->TotSurfaces);
     889         796 :         state.dataSurface->SurfOutWindDir.allocate(state.dataSurface->TotSurfaces);
     890         796 :         state.dataSurface->SurfGenericContam.allocate(state.dataSurface->TotSurfaces);
     891         796 :         state.dataSurface->SurfPenumbraID.allocate(state.dataSurface->TotSurfaces);
     892         796 :         state.dataSurface->SurfAirSkyRadSplit.allocate(state.dataSurface->TotSurfaces);
     893       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     894       46044 :             state.dataSurface->SurfOutDryBulbTemp(SurfNum) = 0.0;
     895       46044 :             state.dataSurface->SurfOutWetBulbTemp(SurfNum) = 0.0;
     896       46044 :             state.dataSurface->SurfOutWindSpeed(SurfNum) = 0.0;
     897       46044 :             state.dataSurface->SurfOutWindDir(SurfNum) = 0.0;
     898       46044 :             state.dataSurface->SurfGenericContam(SurfNum) = 0.0;
     899       46044 :             state.dataSurface->SurfPenumbraID(SurfNum) = -1;
     900       46044 :             state.dataSurface->SurfAirSkyRadSplit(SurfNum) = 0.0;
     901             :         }
     902             :         // Following are surface property arrays used in SurfaceGeometry
     903         796 :         state.dataSurface->SurfShadowRecSurfNum.allocate(state.dataSurface->TotSurfaces);
     904         796 :         state.dataSurface->SurfShadowDisabledZoneList.allocate(state.dataSurface->TotSurfaces);
     905         796 :         state.dataSurface->SurfShadowDiffuseSolRefl.allocate(state.dataSurface->TotSurfaces);
     906         796 :         state.dataSurface->SurfShadowDiffuseVisRefl.allocate(state.dataSurface->TotSurfaces);
     907         796 :         state.dataSurface->SurfShadowGlazingFrac.allocate(state.dataSurface->TotSurfaces);
     908         796 :         state.dataSurface->SurfShadowGlazingConstruct.allocate(state.dataSurface->TotSurfaces);
     909         796 :         state.dataSurface->SurfMaterialMovInsulExt.allocate(state.dataSurface->TotSurfaces);
     910         796 :         state.dataSurface->SurfMaterialMovInsulInt.allocate(state.dataSurface->TotSurfaces);
     911         796 :         state.dataSurface->SurfSchedMovInsulExt.allocate(state.dataSurface->TotSurfaces);
     912         796 :         state.dataSurface->SurfSchedMovInsulInt.allocate(state.dataSurface->TotSurfaces);
     913       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     914       46044 :             state.dataSurface->SurfShadowRecSurfNum(SurfNum) = 0;
     915       46044 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) = 0.0;
     916       46044 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) = 0.0;
     917       46044 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = 0.0;
     918       46044 :             state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = 0;
     919       46044 :             state.dataSurface->SurfMaterialMovInsulExt(SurfNum) = 0;
     920       46044 :             state.dataSurface->SurfMaterialMovInsulInt(SurfNum) = 0;
     921       46044 :             state.dataSurface->SurfSchedMovInsulExt(SurfNum) = 0;
     922       46044 :             state.dataSurface->SurfSchedMovInsulInt(SurfNum) = 0;
     923             :         }
     924         796 :         state.dataSurface->SurfExtEcoRoof.allocate(state.dataSurface->TotSurfaces);
     925         796 :         state.dataSurface->SurfExtCavityPresent.allocate(state.dataSurface->TotSurfaces);
     926         796 :         state.dataSurface->SurfExtCavNum.allocate(state.dataSurface->TotSurfaces);
     927         796 :         state.dataSurface->SurfIsPV.allocate(state.dataSurface->TotSurfaces);
     928         796 :         state.dataSurface->SurfIsICS.allocate(state.dataSurface->TotSurfaces);
     929         796 :         state.dataSurface->SurfIsPool.allocate(state.dataSurface->TotSurfaces);
     930         796 :         state.dataSurface->SurfICSPtr.allocate(state.dataSurface->TotSurfaces);
     931         796 :         state.dataSurface->SurfIsRadSurfOrVentSlabOrPool.allocate(state.dataSurface->TotSurfaces);
     932         796 :         state.dataSurface->SurfDaylightingShelfInd.allocate(state.dataSurface->TotSurfaces);
     933       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     934       46044 :             state.dataSurface->SurfExtEcoRoof(SurfNum) = false;
     935       46044 :             state.dataSurface->SurfExtCavityPresent(SurfNum) = false;
     936       46044 :             state.dataSurface->SurfExtCavNum(SurfNum) = 0;
     937       46044 :             state.dataSurface->SurfIsPV(SurfNum) = false;
     938       46044 :             state.dataSurface->SurfIsICS(SurfNum) = false;
     939       46044 :             state.dataSurface->SurfIsPool(SurfNum) = false;
     940       46044 :             state.dataSurface->SurfICSPtr(SurfNum) = 0;
     941       46044 :             state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(SurfNum) = false;
     942       46044 :             state.dataSurface->SurfDaylightingShelfInd(SurfNum) = 0;
     943             :         }
     944         796 :         state.dataSurface->SurfLowTempErrCount.allocate(state.dataSurface->TotSurfaces);
     945         796 :         state.dataSurface->SurfHighTempErrCount.allocate(state.dataSurface->TotSurfaces);
     946         796 :         state.dataSurface->surfIntConv.allocate(state.dataSurface->TotSurfaces);
     947         796 :         state.dataSurface->SurfTAirRef.allocate(state.dataSurface->TotSurfaces);
     948         796 :         state.dataSurface->SurfTAirRefRpt.allocate(state.dataSurface->TotSurfaces);
     949         796 :         state.dataSurface->surfExtConv.allocate(state.dataSurface->TotSurfaces);
     950       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     951       46044 :             state.dataSurface->SurfLowTempErrCount(SurfNum) = 0;
     952       46044 :             state.dataSurface->SurfHighTempErrCount(SurfNum) = 0;
     953       46044 :             state.dataSurface->surfIntConv(SurfNum) = SurfIntConv();
     954       46044 :             state.dataSurface->surfExtConv(SurfNum) = SurfExtConv();
     955       46044 :             state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::Invalid;
     956       46044 :             state.dataSurface->SurfTAirRefRpt(SurfNum) = static_cast<int>(DataSurfaces::RefAirTemp::Invalid);
     957             :         }
     958         796 :     }
     959             : 
     960         796 :     void GetSurfaceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
     961             :     {
     962             : 
     963             :         // SUBROUTINE INFORMATION:
     964             :         //       AUTHOR         Richard Liesen
     965             :         //       DATE WRITTEN   November 1997
     966             :         //       MODIFIED       April 1999, Linda Lawrie
     967             :         //                      Dec. 2000, FW (add "one-wall zone" checks)
     968             :         //       RE-ENGINEERED  May 2000, Linda Lawrie (breakout surface type gets)
     969             : 
     970             :         // PURPOSE OF THIS SUBROUTINE:
     971             :         // The purpose of this subroutine is to read in the surface information
     972             :         // from the input data file and interpret and put in the derived type
     973             : 
     974             :         // METHODOLOGY EMPLOYED:
     975             :         // The order of surfaces does not matter and the surfaces are resorted into
     976             :         // the hierarchical order:
     977             :         //  All Shading Surfaces
     978             :         //  Airwalls for space x1
     979             :         //  Base Surfaces for space x1
     980             :         //  Opaque Subsurfaces for space x1
     981             :         //  Window Subsurfaces for space x1
     982             :         //  TDD Dome Surfaces for space x1
     983             :         //  Airwalls for space x2
     984             :         //  Base Surfaces for space x2
     985             :         //  etc
     986             :         //  Pointers are set in the spaces (AllSurfaceFirst/Last, HTSurfaceFirst/Last, OpaqOrIntMassSurfaceFirst/Last, WindowSurfaceFirst/Last,
     987             :         //  OpaqOrWinSurfaceFirst/Last, TDDDomeFirst/Last)
     988             : 
     989             :         // REFERENCES:
     990             :         //   This routine manages getting the input for the following Objects:
     991             :         // SurfaceGeometry
     992             :         // Surface:Shading:Detached
     993             :         // Surface:HeatTransfer
     994             :         // Surface:HeatTransfer:Sub
     995             :         // Surface:Shading:Attached
     996             :         // Surface:InternalMass
     997             : 
     998             :         // Vertex input:
     999             :         //  N3 , \field Number of Surface Vertices -- Number of (X,Y,Z) groups in this surface
    1000             :         //       \note currently limited 3 or 4, later?
    1001             :         //       \min 3
    1002             :         //       \max 4
    1003             :         //       \memo vertices are given in SurfaceGeometry coordinates -- if relative, all surface coordinates
    1004             :         //       \memo are "relative" to the Zone Origin.  if WCS, then building and zone origins are used
    1005             :         //       \memo for some internal calculations, but all coordinates are given in an "absolute" system.
    1006             :         //  N4,  \field Vertex 1 X-coordinate
    1007             :         //       \units m
    1008             :         //       \type real
    1009             :         //  N5 , \field Vertex 1 Y-coordinate
    1010             :         //       \units m
    1011             :         //       \type real
    1012             :         //  N6 , \field Vertex 1 Z-coordinate
    1013             :         //       \units m
    1014             :         //       \type real
    1015             :         //  N7,  \field Vertex 2 X-coordinate
    1016             :         //       \units m
    1017             :         //       \type real
    1018             :         //  N8,  \field Vertex 2 Y-coordinate
    1019             :         //       \units m
    1020             :         //       \type real
    1021             :         //  N9,  \field Vertex 2 Z-coordinate
    1022             :         //       \units m
    1023             :         //       \type real
    1024             :         //  N10, \field Vertex 3 X-coordinate
    1025             :         //       \units m
    1026             :         //       \type real
    1027             :         //  N11, \field Vertex 3 Y-coordinate
    1028             :         //       \units m
    1029             :         //       \type real
    1030             :         //  N12, \field Vertex 3 Z-coordinate
    1031             :         //       \units m
    1032             :         //       \type real
    1033             :         //  N13, \field Vertex 4 X-coordinate
    1034             :         //       \units m
    1035             :         //       \type real
    1036             :         //  N14, \field Vertex 4 Y-coordinate
    1037             :         //       \type real
    1038             :         //       \units m
    1039             :         //  N15; \field Vertex 4 Z-coordinate
    1040             :         //       \units m
    1041             :         //       \type real
    1042             : 
    1043             :         // The vertices are stored in the surface derived type.
    1044             :         //      +(1)-------------------------(4)+
    1045             :         //      |                               |
    1046             :         //      |                               |
    1047             :         //      |                               |
    1048             :         //      +(2)-------------------------(3)+
    1049             :         //  The above diagram shows the actual coordinate points of a typical wall
    1050             :         //  (you're on the outside looking toward the wall) as stored into
    1051             :         //  Surface%Vertex(1:<number-of-sides>)
    1052             : 
    1053             :         using namespace Vectors;
    1054             :         using ScheduleManager::GetScheduleMaxValue;
    1055             :         using ScheduleManager::GetScheduleMinValue;
    1056             :         using namespace DataErrorTracking;
    1057             : 
    1058             :         static constexpr std::string_view RoutineName("GetSurfaceData: ");
    1059             : 
    1060             :         int ConstrNum;            // Construction number
    1061             :         int Found;                // For matching interzone surfaces
    1062             :         int ConstrNumFound;       // Construction number of matching interzone surface
    1063         796 :         bool NonMatch(false);     // Error for non-matching interzone surfaces
    1064             :         int MovedSurfs;           // Number of Moved Surfaces (when sorting into hierarchical structure)
    1065         796 :         bool SurfError(false);    // General Surface Error, causes fatal error at end of routine
    1066             :         int TotLay;               // Total layers in a construction
    1067             :         int TotLayFound;          // Total layers in the construction of a matching interzone surface
    1068             :         int TotDetachedFixed;     // Total Shading:Site:Detailed entries
    1069             :         int TotDetachedBldg;      // Total Shading:Building:Detailed entries
    1070             :         int TotRectDetachedFixed; // Total Shading:Site entries
    1071             :         int TotRectDetachedBldg;  // Total Shading:Building entries
    1072             :         int TotHTSurfs;           // Number of BuildingSurface:Detailed items to obtain
    1073             :         int TotDetailedWalls;     // Number of Wall:Detailed items to obtain
    1074             :         int TotDetailedRoofs;     // Number of RoofCeiling:Detailed items to obtain
    1075             :         int TotDetailedFloors;    // Number of Floor:Detailed items to obtain
    1076             :         int TotHTSubs;            // Number of FenestrationSurface:Detailed items to obtain
    1077             :         int TotShdSubs;           // Number of Shading:Zone:Detailed items to obtain
    1078             :         int TotIntMassSurfaces;   // Number of InternalMass surfaces to obtain
    1079             :         // Simple Surfaces (Rectangular)
    1080             :         int TotRectExtWalls;   // Number of Exterior Walls to obtain
    1081             :         int TotRectIntWalls;   // Number of Adiabatic Walls to obtain
    1082             :         int TotRectIZWalls;    // Number of Interzone Walls to obtain
    1083             :         int TotRectUGWalls;    // Number of Underground to obtain
    1084             :         int TotRectRoofs;      // Number of Roofs to obtain
    1085             :         int TotRectCeilings;   // Number of Adiabatic Ceilings to obtain
    1086             :         int TotRectIZCeilings; // Number of Interzone Ceilings to obtain
    1087             :         int TotRectGCFloors;   // Number of Floors with Ground Contact to obtain
    1088             :         int TotRectIntFloors;  // Number of Adiabatic Walls to obtain
    1089             :         int TotRectIZFloors;   // Number of Interzone Floors to obtain
    1090             :         int TotRectWindows;
    1091             :         int TotRectDoors;
    1092             :         int TotRectGlazedDoors;
    1093             :         int TotRectIZWindows;
    1094             :         int TotRectIZDoors;
    1095             :         int TotRectIZGlazedDoors;
    1096             :         int TotOverhangs;
    1097             :         int TotOverhangsProjection;
    1098             :         int TotFins;
    1099             :         int TotFinsProjection;
    1100         796 :         bool RelWarning(false);
    1101             :         int ConstrNumSh;      // Shaded construction number for a window
    1102             :         int LayNumOutside;    // Outside material numbers for a shaded construction
    1103             :         int BlNum;            // Blind number
    1104             :         int AddedSubSurfaces; // Subsurfaces (windows) added when windows reference Window5 Data File
    1105             :         // entries with two glazing systems
    1106             :         int NeedToAddSurfaces;    // Surfaces that will be added due to "unentered" other zone surface
    1107             :         int NeedToAddSubSurfaces; // SubSurfaces that will be added due to "unentered" other zone surface
    1108             :         int CurNewSurf;
    1109             :         int FirstTotalSurfaces;
    1110             :         int NVert;
    1111             :         int Vert;
    1112             :         int n;
    1113             :         Real64 SurfWorldAz;
    1114             :         Real64 SurfTilt;
    1115             : 
    1116             :         int MultFound;
    1117             :         int MultSurfNum;
    1118         796 :         std::string MultString;
    1119             :         bool SubSurfaceSevereDisplayed;
    1120         796 :         bool subSurfaceError(false);
    1121             :         bool errFlag;
    1122             : 
    1123             :         int iTmp1;
    1124             :         int iTmp2;
    1125             :         // unused  INTEGER :: SchID
    1126             :         int BlNumNew;
    1127         796 :         int WinShadingControlPtr(0);
    1128             :         int ErrCount;
    1129             :         bool izConstDiff;    // differences in construction for IZ surfaces
    1130             :         bool izConstDiffMsg; // display message about hb diffs only once.
    1131             : 
    1132             :         // Get the total number of surfaces to allocate derived type and for surface loops
    1133             : 
    1134         796 :         if (state.dataSurfaceGeometry->GetSurfaceDataOneTimeFlag) {
    1135           0 :             return;
    1136             :         } else {
    1137         796 :             state.dataSurfaceGeometry->GetSurfaceDataOneTimeFlag = true;
    1138             :         }
    1139             : 
    1140         796 :         GetGeometryParameters(state, ErrorsFound);
    1141             : 
    1142         796 :         if (state.dataSurface->WorldCoordSystem) {
    1143         357 :             if (state.dataHeatBal->BuildingAzimuth != 0.0) RelWarning = true;
    1144        1392 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1145        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).RelNorth != 0.0) RelWarning = true;
    1146             :             }
    1147         357 :             if (RelWarning && !state.dataSurfaceGeometry->WarningDisplayed) {
    1148           2 :                 ShowWarningError(
    1149             :                     state,
    1150           2 :                     format("{}World Coordinate System selected.  Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.",
    1151             :                            RoutineName));
    1152           1 :                 ShowContinueError(state,
    1153             :                                   "These may be used in daylighting reference point coordinate calculations but not in normal geometry inputs.");
    1154           1 :                 state.dataSurfaceGeometry->WarningDisplayed = true;
    1155             :             }
    1156         357 :             RelWarning = false;
    1157        1392 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1158        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginX != 0.0) RelWarning = true;
    1159        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginY != 0.0) RelWarning = true;
    1160        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginZ != 0.0) RelWarning = true;
    1161             :             }
    1162         357 :             if (RelWarning && !state.dataSurfaceGeometry->WarningDisplayed) {
    1163          24 :                 ShowWarningError(
    1164             :                     state,
    1165          24 :                     format("{}World Coordinate System selected.  Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.",
    1166             :                            RoutineName));
    1167          12 :                 ShowContinueError(state,
    1168             :                                   "These may be used in daylighting reference point coordinate calculations but not in normal geometry inputs.");
    1169          12 :                 state.dataSurfaceGeometry->WarningDisplayed = true;
    1170             :             }
    1171             :         }
    1172             : 
    1173         796 :         TotDetachedFixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Site:Detailed");
    1174         796 :         TotDetachedBldg = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Building:Detailed");
    1175         796 :         TotRectDetachedFixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Site");
    1176         796 :         TotRectDetachedBldg = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Building");
    1177         796 :         TotHTSurfs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "BuildingSurface:Detailed");
    1178         796 :         TotDetailedWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Detailed");
    1179         796 :         TotDetailedRoofs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "RoofCeiling:Detailed");
    1180         796 :         TotDetailedFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Detailed");
    1181         796 :         TotHTSubs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "FenestrationSurface:Detailed");
    1182         796 :         TotShdSubs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Zone:Detailed");
    1183         796 :         TotOverhangs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Overhang");
    1184         796 :         TotOverhangsProjection = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Overhang:Projection");
    1185         796 :         TotFins = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Fin");
    1186         796 :         TotFinsProjection = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Fin:Projection");
    1187         796 :         TotRectWindows = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Window");
    1188         796 :         TotRectDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Door");
    1189         796 :         TotRectGlazedDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "GlazedDoor");
    1190         796 :         TotRectIZWindows = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Window:Interzone");
    1191         796 :         TotRectIZDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Door:Interzone");
    1192         796 :         TotRectIZGlazedDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "GlazedDoor:Interzone");
    1193         796 :         TotRectExtWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Exterior");
    1194         796 :         TotRectIntWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Adiabatic");
    1195         796 :         TotRectIZWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Interzone");
    1196         796 :         TotRectUGWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Underground");
    1197         796 :         TotRectRoofs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Roof");
    1198         796 :         TotRectCeilings = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Ceiling:Adiabatic");
    1199         796 :         TotRectIZCeilings = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Ceiling:Interzone");
    1200         796 :         TotRectGCFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:GroundContact");
    1201         796 :         TotRectIntFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Adiabatic");
    1202         796 :         TotRectIZFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Interzone");
    1203             : 
    1204         796 :         state.dataSurface->TotOSC = 0;
    1205             : 
    1206         796 :         TotIntMassSurfaces = GetNumIntMassSurfaces(state);
    1207             : 
    1208        1592 :         state.dataSurface->TotSurfaces = (TotDetachedFixed + TotDetachedBldg + TotRectDetachedFixed + TotRectDetachedBldg) * 2 + TotHTSurfs +
    1209         796 :                                          TotHTSubs + TotShdSubs * 2 + TotIntMassSurfaces + TotOverhangs * 2 + TotOverhangsProjection * 2 +
    1210         796 :                                          TotFins * 4 + TotFinsProjection * 4 + TotDetailedWalls + TotDetailedRoofs + TotDetailedFloors +
    1211         796 :                                          TotRectWindows + TotRectDoors + TotRectGlazedDoors + TotRectIZWindows + TotRectIZDoors +
    1212         796 :                                          TotRectIZGlazedDoors + TotRectExtWalls + TotRectIntWalls + TotRectIZWalls + TotRectUGWalls + TotRectRoofs +
    1213         796 :                                          TotRectCeilings + TotRectIZCeilings + TotRectGCFloors + TotRectIntFloors + TotRectIZFloors;
    1214             : 
    1215         796 :         state.dataSurfaceGeometry->SurfaceTmp.allocate(state.dataSurface->TotSurfaces); // Allocate the Surface derived type appropriately
    1216         796 :         state.dataSurfaceGeometry->UniqueSurfaceNames.reserve(state.dataSurface->TotSurfaces);
    1217             :         // SurfaceTmp structure is allocated via derived type initialization.
    1218             : 
    1219         796 :         int NumSurfs = 0;
    1220         796 :         AddedSubSurfaces = 0;
    1221         796 :         state.dataErrTracking->AskForSurfacesReport = true;
    1222             : 
    1223         796 :         GetDetShdSurfaceData(state, ErrorsFound, NumSurfs, TotDetachedFixed, TotDetachedBldg);
    1224             : 
    1225         796 :         GetRectDetShdSurfaceData(state, ErrorsFound, NumSurfs, TotRectDetachedFixed, TotRectDetachedBldg);
    1226             : 
    1227         796 :         GetHTSurfaceData(state,
    1228             :                          ErrorsFound,
    1229             :                          NumSurfs,
    1230             :                          TotHTSurfs,
    1231             :                          TotDetailedWalls,
    1232             :                          TotDetailedRoofs,
    1233             :                          TotDetailedFloors,
    1234         796 :                          state.dataSurfaceGeometry->BaseSurfCls,
    1235         796 :                          state.dataSurfaceGeometry->BaseSurfIDs,
    1236             :                          NeedToAddSurfaces);
    1237             : 
    1238         796 :         GetRectSurfaces(state,
    1239             :                         ErrorsFound,
    1240             :                         NumSurfs,
    1241             :                         TotRectExtWalls,
    1242             :                         TotRectIntWalls,
    1243             :                         TotRectIZWalls,
    1244             :                         TotRectUGWalls,
    1245             :                         TotRectRoofs,
    1246             :                         TotRectCeilings,
    1247             :                         TotRectIZCeilings,
    1248             :                         TotRectGCFloors,
    1249             :                         TotRectIntFloors,
    1250             :                         TotRectIZFloors,
    1251         796 :                         state.dataSurfaceGeometry->BaseSurfIDs,
    1252             :                         NeedToAddSurfaces);
    1253             : 
    1254         796 :         GetHTSubSurfaceData(state,
    1255             :                             ErrorsFound,
    1256             :                             NumSurfs,
    1257             :                             TotHTSubs,
    1258         796 :                             state.dataSurfaceGeometry->SubSurfCls,
    1259         796 :                             state.dataSurfaceGeometry->SubSurfIDs,
    1260             :                             AddedSubSurfaces,
    1261             :                             NeedToAddSubSurfaces);
    1262             : 
    1263         796 :         GetRectSubSurfaces(state,
    1264             :                            ErrorsFound,
    1265             :                            NumSurfs,
    1266             :                            TotRectWindows,
    1267             :                            TotRectDoors,
    1268             :                            TotRectGlazedDoors,
    1269             :                            TotRectIZWindows,
    1270             :                            TotRectIZDoors,
    1271             :                            TotRectIZGlazedDoors,
    1272         796 :                            state.dataSurfaceGeometry->SubSurfIDs,
    1273             :                            AddedSubSurfaces,
    1274             :                            NeedToAddSubSurfaces);
    1275             : 
    1276         796 :         GetAttShdSurfaceData(state, ErrorsFound, NumSurfs, TotShdSubs);
    1277             : 
    1278         796 :         GetSimpleShdSurfaceData(state, ErrorsFound, NumSurfs, TotOverhangs, TotOverhangsProjection, TotFins, TotFinsProjection);
    1279             : 
    1280         796 :         GetIntMassSurfaceData(state, ErrorsFound, NumSurfs);
    1281             : 
    1282         796 :         state.dataSurface->TotSurfaces = NumSurfs + AddedSubSurfaces + NeedToAddSurfaces + NeedToAddSubSurfaces;
    1283             : 
    1284         796 :         if (ErrorsFound) {
    1285           0 :             ShowFatalError(state, format("{}Errors discovered, program terminates.", RoutineName));
    1286             :         }
    1287             : 
    1288         796 :         state.dataSurface->Surface.allocate(state.dataSurface->TotSurfaces); // Allocate the Surface derived type appropriately
    1289         796 :         state.dataSurface->SurfaceWindow.allocate(state.dataSurface->TotSurfaces);
    1290         796 :         AllocateSurfaceArrays(state);
    1291         796 :         AllocateSurfaceWindows(state, state.dataSurface->TotSurfaces);
    1292             : 
    1293             :         // Have to make room for added surfaces, if needed
    1294         796 :         FirstTotalSurfaces = NumSurfs + AddedSubSurfaces;
    1295         796 :         if (NeedToAddSurfaces + NeedToAddSubSurfaces > 0) {
    1296          31 :             state.dataSurfaceGeometry->SurfaceTmp.redimension(state.dataSurface->TotSurfaces);
    1297             :         }
    1298             : 
    1299             :         // add the "need to add" surfaces
    1300             :         // Debug    write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces
    1301         796 :         if (NeedToAddSurfaces + NeedToAddSubSurfaces > 0) CurNewSurf = FirstTotalSurfaces;
    1302       46470 :         for (int SurfNum = 1; SurfNum <= FirstTotalSurfaces; ++SurfNum) {
    1303       45674 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != UnenteredAdjacentZoneSurface) continue;
    1304             :             // Need to add surface
    1305         370 :             ++CurNewSurf;
    1306             :             // Debug    write(outputfiledebug,*) ' adding surface=',curnewsurf
    1307         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1308             :             //  Basic parameters are the same for both surfaces.
    1309         370 :             Found = Util::FindItemInList(
    1310         370 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    1311         370 :             if (Found == 0) continue;
    1312         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = Found;
    1313         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataHeatBal->Zone(Found).Name;
    1314             :             // Reverse Construction
    1315         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction =
    1316         370 :                 AssignReverseConstructionNumber(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction, SurfError);
    1317         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConstructionStoredInputValue =
    1318         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction;
    1319             :             // Reverse Vertices
    1320         370 :             NVert = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
    1321        1850 :             for (Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) {
    1322        1480 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex(Vert) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NVert);
    1323        1480 :                 --NVert;
    1324             :             }
    1325         370 :             if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides > 2) {
    1326         370 :                 CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
    1327         370 :                                        state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
    1328         370 :                                        state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector);
    1329         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea =
    1330         370 :                     VecLength(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector);
    1331         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea;
    1332         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
    1333         370 :                 CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
    1334         370 :                                                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
    1335         370 :                                                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector);
    1336         370 :                 DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
    1337             :                                         SurfWorldAz,
    1338             :                                         SurfTilt,
    1339         370 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsx,
    1340         370 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsy,
    1341         370 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsz,
    1342         370 :                                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector);
    1343         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Azimuth = SurfWorldAz;
    1344         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt = SurfTilt;
    1345         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).convOrientation =
    1346         370 :                     Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt);
    1347             : 
    1348             :                 // Sine and cosine of azimuth and tilt
    1349         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinAzim = std::sin(SurfWorldAz * Constant::DegToRadians);
    1350         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosAzim = std::cos(SurfWorldAz * Constant::DegToRadians);
    1351         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinTilt = std::sin(SurfTilt * Constant::DegToRadians);
    1352         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt = std::cos(SurfTilt * Constant::DegToRadians);
    1353             :                 // Outward normal unit vector (pointing away from room)
    1354         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec =
    1355         740 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector;
    1356        1480 :                 for (n = 1; n <= 3; ++n) {
    1357        1110 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) - 1.0) < 1.e-06)
    1358          87 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = +1.0;
    1359        1110 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) + 1.0) < 1.e-06)
    1360         241 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = -1.0;
    1361        1110 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n)) < 1.e-06)
    1362         698 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = 0.0;
    1363             :                 }
    1364             : 
    1365             :                 // Can perform tests on this surface here
    1366         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky =
    1367         370 :                     0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
    1368         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGround =
    1369         370 :                     0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
    1370             : 
    1371             :                 // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    1372             :                 // surfaces
    1373         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky;
    1374         370 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGroundIR =
    1375         370 :                     0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
    1376             :             }
    1377             : 
    1378             :             // Change Name
    1379         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name = "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    1380             :             // Debug   write(outputfiledebug,*) ' new surf name=',TRIM(SurfaceTmp(CurNewSurf)%Name)
    1381             :             // Debug   write(outputfiledebug,*) ' new surf in zone=',TRIM(surfacetmp(curnewsurf)%zoneName)
    1382         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = UnreconciledZoneSurface;
    1383         370 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    1384         370 :             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    1385         370 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name;
    1386         370 :             if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Roof ||
    1387         390 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Wall ||
    1388          20 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Floor) {
    1389             :                 // base surface
    1390         366 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof) {
    1391          96 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Floor;
    1392             :                     // Debug          write(outputfiledebug,*) ' new surfaces is a floor'
    1393         270 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor) {
    1394          16 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Roof;
    1395             :                     // Debug          write(outputfiledebug,*) ' new surfaces is a roof'
    1396             :                 }
    1397         366 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = CurNewSurf;
    1398         366 :                 state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name;
    1399             :                 // Debug        write(outputfiledebug,*) ' basesurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
    1400             :             } else {
    1401             :                 // subsurface
    1402           4 :                 Found = Util::FindItemInList("iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    1403           4 :                                              state.dataSurfaceGeometry->SurfaceTmp,
    1404           4 :                                              FirstTotalSurfaces + CurNewSurf - 1);
    1405           4 :                 if (Found > 0) {
    1406           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName =
    1407           8 :                         "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
    1408           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = Found;
    1409           4 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
    1410           7 :                     if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Window ||
    1411           3 :                         state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::GlassDoor) {
    1412           2 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -=
    1413           2 :                             state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area / state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Multiplier;
    1414             :                     } else { // Door, TDD:Diffuser, TDD:DOME
    1415           2 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
    1416             :                     }
    1417           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    1418           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    1419           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    1420           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    1421           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
    1422           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
    1423           4 :                     state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
    1424             :                     // Debug        write(outputfiledebug,*) ' subsurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
    1425             :                     // Debug        write(outputfiledebug,*) ' subsurf, basesurf=',TRIM('iz-'//SurfaceTmp(SurfNum)%BaseSurfName)
    1426             :                 } else {
    1427           0 :                     ShowSevereError(state,
    1428           0 :                                     format("{}Adding unentered subsurface, could not find base surface=iz-{}",
    1429             :                                            RoutineName,
    1430           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName));
    1431           0 :                     SurfError = true;
    1432             :                 }
    1433             :             }
    1434             :         }
    1435             :         //**********************************************************************************
    1436             :         // After all of the surfaces have been defined then the base surfaces for the
    1437             :         // sub-surfaces can be defined.  Loop through surfaces and match with the sub-surface
    1438             :         // names.
    1439       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1440       46044 :             if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) continue;
    1441             : 
    1442             :             // why are we doing this again?  this should have already been done.
    1443       44408 :             if (Util::SameString(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) {
    1444       37710 :                 Found = SurfNum;
    1445             :             } else {
    1446        6698 :                 Found = Util::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    1447        6698 :                                              state.dataSurfaceGeometry->SurfaceTmp,
    1448        6698 :                                              state.dataSurface->TotSurfaces);
    1449             :             }
    1450       44408 :             if (Found > 0) {
    1451       44408 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
    1452       44408 :                 if (SurfNum != Found) { // for subsurfaces
    1453        6698 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) ++state.dataSurfaceGeometry->SurfaceTmp(Found).NumSubSurfaces;
    1454       13396 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class < SurfaceClass::Window ||
    1455        6698 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class > SurfaceClass::TDD_Diffuser) {
    1456           0 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::None) {
    1457           0 :                             ShowSevereError(state,
    1458           0 :                                             format("{}Invalid SubSurface detected, Surface={}",
    1459             :                                                    RoutineName,
    1460           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    1461             :                         } else {
    1462           0 :                             ShowSevereError(
    1463             :                                 state,
    1464           0 :                                 format("{}Invalid SubSurface detected, Surface={}, class={} invalid class for subsurface",
    1465             :                                        RoutineName,
    1466           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    1467           0 :                                        state.dataSurfaceGeometry->BaseSurfCls(int(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class))));
    1468           0 :                             SurfError = true;
    1469             :                         }
    1470             :                     }
    1471             :                 }
    1472             :             }
    1473             : 
    1474             :         } // ...end of the Surface DO loop for finding BaseSurf
    1475             :         //**********************************************************************************
    1476             :         // The surfaces need to be hierarchical by space.  Input is allowed to be in any order.  In
    1477             :         // this section the surfaces are reordered into:
    1478             :         //    All shadowing surfaces (if mirrored, Mir- surface follows immediately after original)
    1479             :         //      Shading:Site
    1480             :         //      Shading:Building
    1481             :         //      Shading:space (and variants)
    1482             :         //    For each space:
    1483             :         //      Walls
    1484             :         //      Floors
    1485             :         //      Roofs/Ceilings
    1486             :         //      Internal Mass
    1487             :         //      Non-Window subsurfaces (including doors)
    1488             :         //      Window subsurfaces (including TubularDaylightingDiffusers)
    1489             :         //      TubularDaylightingDomes
    1490             :         //    After reordering, MovedSurfs should equal TotSurfaces
    1491             : 
    1492             :         // For reporting purposes, the legacy surface order is also saved in DataSurfaces::AllSurfaceListReportOrder:
    1493             :         //    All shadowing surfaces (if mirrored, Mir- surface follows immediately after original)
    1494             :         //      Shading:Site
    1495             :         //      Shading:Building
    1496             :         //      Shading:Zone (and variants)
    1497             :         //    For each zone:
    1498             :         //      Walls
    1499             :         //        subsurfaces for each wall (windows, doors, in input order, not sorted) follow the base surface
    1500             :         //      Floors
    1501             :         //        subsurfaces for each floor (windows, doors, in input order, not sorted) follow the base surface
    1502             :         //      Roofs/Ceilings
    1503             :         //        subsurfaces for each roof/ceiling (windows, doors, in input order, not sorted) follow the base surface
    1504             :         //      Internal Mass
    1505             :         //    After reordering, MovedSurfs should equal TotSurfaces
    1506             : 
    1507         796 :         MovedSurfs = 0;
    1508         796 :         Array1D<bool> SurfaceTmpClassMoved; // Tmp class is moved
    1509         796 :         SurfaceTmpClassMoved.dimension(state.dataSurface->TotSurfaces, false);
    1510         796 :         state.dataSurface->AllSurfaceListReportOrder.reserve(state.dataSurface->TotSurfaces);
    1511             : 
    1512         796 :         CreateMissingSpaces(state, state.dataSurfaceGeometry->SurfaceTmp);
    1513             : 
    1514             :         // Old SurfNum to New SurfNum
    1515             :         // Old = order in state.dataSurfaceGeometry->SurfaceTmp
    1516             :         // New = order in state.dataSurface->Surface
    1517         796 :         EPVector<int> oldToNewSurfNums;
    1518         796 :         oldToNewSurfNums.resize(state.dataSurface->TotSurfaces, -1);
    1519             : 
    1520             :         // Move all shading Surfaces to Front
    1521       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1522       46044 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F &&
    1523       91936 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_B &&
    1524       45892 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Shading)
    1525       44408 :                 continue;
    1526             : 
    1527             :             //  A shading surface
    1528        1636 :             ++MovedSurfs;
    1529             :             // Store list of moved surface numbers in reporting order
    1530        1636 :             state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1531        1636 :             SurfaceTmpClassMoved(SurfNum) = true; //'Moved'
    1532        1636 :             state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1533        1636 :             oldToNewSurfNums(SurfNum) = MovedSurfs;
    1534             :         }
    1535             : 
    1536             :         //  For each zone
    1537             : 
    1538        5852 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1539       10124 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    1540             :                 // Group air boundary surfaces first within each space
    1541     1276522 :                 for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1542     1271454 :                     if (SurfaceTmpClassMoved(SurfNum)) continue;
    1543      655964 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
    1544       44408 :                     int constNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    1545       44408 :                     if (constNum == 0) continue;
    1546       44408 :                     if (!state.dataConstruction->Construct(constNum).TypeIsAirBoundary) continue;
    1547             : 
    1548             :                     //  An air boundary surface
    1549          18 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsAirBoundarySurf = true;
    1550          18 :                     ++MovedSurfs;
    1551          18 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1552             :                     //  If base Surface Type (Wall, Floor, Roof/Ceiling)
    1553          18 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(1)) ||
    1554          18 :                         (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(2)) ||
    1555           0 :                         (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(3))) {
    1556             :                         // Store list of moved surface numbers in reporting order. We use the old position, we'll reconcile later
    1557             :                         // We don't do it for Air Door/Air Windows yet, we want them listed below each base surf they belong to
    1558          18 :                         state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1559             :                     }
    1560          18 :                     oldToNewSurfNums(SurfNum) = MovedSurfs;
    1561          18 :                     SurfaceTmpClassMoved(SurfNum) = true; //'Moved'
    1562             :                 }
    1563             : 
    1564             :                 //  For each Base Surface Type (Wall, Floor, Roof/Ceiling) - put these first
    1565             : 
    1566       20272 :                 for (const DataSurfaces::SurfaceClass Loop : state.dataSurfaceGeometry->BaseSurfIDs) {
    1567             : 
    1568     3829566 :                     for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1569             : 
    1570     3814362 :                         if (SurfaceTmpClassMoved(SurfNum)) continue;
    1571     1915742 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone == 0) continue;
    1572             : 
    1573     1915742 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
    1574       81074 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != Loop) continue;
    1575             : 
    1576       35294 :                         ++MovedSurfs;
    1577       35294 :                         state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1578       35294 :                         oldToNewSurfNums(SurfNum) = MovedSurfs;
    1579       35294 :                         SurfaceTmpClassMoved(SurfNum) = true; // 'Moved'
    1580             :                         // Store list of moved surface numbers in order reporting order (subsurfaces follow their base surface)
    1581       35294 :                         state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1582             : 
    1583             :                         //  Find all subsurfaces to this surface - just to update Report them in order
    1584     9280844 :                         for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1585             :                             // Gotta avoid pushing myself again!
    1586     9245550 :                             if (SubSurfNum == SurfNum) continue;
    1587             :                             // We don't check if already moved, because we didn't add them to AllSurfaceListReportOrder above!
    1588     9210256 :                             if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Zone == 0) continue;
    1589     9133486 :                             if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).BaseSurf != SurfNum) continue;
    1590             :                             // Add original sub-surface numbers as placeholders in surface list for reporting
    1591        6698 :                             state.dataSurface->AllSurfaceListReportOrder.push_back(SubSurfNum);
    1592             :                         }
    1593             :                     }
    1594             :                 }
    1595             : 
    1596             :                 // Internal mass goes next
    1597     1276522 :                 for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1598             : 
    1599     1271454 :                     if (SurfaceTmpClassMoved(SurfNum)) continue;
    1600      620652 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
    1601        9096 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::IntMass) continue;
    1602        2398 :                     ++MovedSurfs;
    1603        2398 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    1604        2398 :                     oldToNewSurfNums(SurfNum) = MovedSurfs;
    1605        2398 :                     SurfaceTmpClassMoved(SurfNum) = true; // 'Moved'
    1606             :                     // Store list of moved surface numbers in reporting order
    1607        2398 :                     state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
    1608             :                 }
    1609             : 
    1610             :                 // Opaque door goes next
    1611     1276522 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1612             : 
    1613     1271454 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1614      618254 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1615        6698 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Door) continue;
    1616             : 
    1617         479 :                     ++MovedSurfs;
    1618         479 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1619         479 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1620         479 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1621             :                 }
    1622             : 
    1623             :                 // The exterior window subsurfaces (includes SurfaceClass::Window and SurfaceClass::GlassDoor) goes next
    1624     1276522 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1625             : 
    1626     1271454 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1627      617775 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1628        6219 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).ExtBoundCond > 0) continue; // Exterior window
    1629        6762 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Window) &&
    1630         543 :                         (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::GlassDoor))
    1631           4 :                         continue;
    1632             : 
    1633        6215 :                     ++MovedSurfs;
    1634        6215 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1635        6215 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1636        6215 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1637             :                 }
    1638             : 
    1639             :                 // The interior window subsurfaces (includes SurfaceClass::Window and SurfaceClass::GlassDoor) goes next
    1640     1276522 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1641             : 
    1642     1271454 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1643      611560 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1644           4 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).ExtBoundCond <= 0) continue;
    1645           0 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Window) &&
    1646           0 :                         (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::GlassDoor))
    1647           0 :                         continue;
    1648             : 
    1649           0 :                     ++MovedSurfs;
    1650           0 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1651           0 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1652           0 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1653             :                 }
    1654             : 
    1655             :                 // The SurfaceClass::TDD_Diffuser (OriginalClass = Window) goes next
    1656     1276522 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1657             : 
    1658     1271454 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1659      611560 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1660           4 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::TDD_Diffuser) continue;
    1661             : 
    1662           2 :                     ++MovedSurfs;
    1663           2 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1664           2 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1665           2 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1666             :                 }
    1667             : 
    1668             :                 // Last but not least, SurfaceClass::TDD_Dome
    1669     1276522 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1670             : 
    1671     1271454 :                     if (SurfaceTmpClassMoved(SubSurfNum)) continue;
    1672      611558 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
    1673           2 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::TDD_Dome) continue;
    1674             : 
    1675           2 :                     ++MovedSurfs;
    1676           2 :                     state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
    1677           2 :                     oldToNewSurfNums(SubSurfNum) = MovedSurfs;
    1678           2 :                     SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
    1679             :                 }
    1680        5056 :             }
    1681             :         }
    1682             : 
    1683             :         // Validity checking
    1684         796 :         assert(state.dataSurface->TotSurfaces == MovedSurfs);
    1685         796 :         assert(state.dataSurface->TotSurfaces == static_cast<int>(state.dataSurface->AllSurfaceListReportOrder.size()));
    1686         796 :         assert(state.dataSurface->TotSurfaces == static_cast<int>(oldToNewSurfNums.size()));
    1687             : 
    1688             :         // Assert validity of indices
    1689       46840 :         assert(std::find_if(state.dataSurface->AllSurfaceListReportOrder.cbegin(), state.dataSurface->AllSurfaceListReportOrder.cend(), [](int i) {
    1690             :                    return i < 1;
    1691             :                }) == state.dataSurface->AllSurfaceListReportOrder.cend());
    1692             : 
    1693       46840 :         assert(std::find_if(oldToNewSurfNums.cbegin(), oldToNewSurfNums.cend(), [](int i) { return i < 1; }) == oldToNewSurfNums.cend());
    1694             : 
    1695         796 :         if (MovedSurfs != state.dataSurface->TotSurfaces) {
    1696           0 :             ShowSevereError(
    1697             :                 state,
    1698           0 :                 format("{}Reordered # of Surfaces ({}) not = Total # of Surfaces ({})", RoutineName, MovedSurfs, state.dataSurface->TotSurfaces));
    1699           0 :             SurfError = true;
    1700           0 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfaces; ++Loop) {
    1701           0 :                 if (!SurfaceTmpClassMoved(Loop) && state.dataSurfaceGeometry->SurfaceTmp(Loop).Class == SurfaceClass::Invalid) {
    1702           0 :                     ShowSevereError(state,
    1703           0 :                                     format("{}Error in Surface= \"{} indicated Zone=\"{}\"",
    1704             :                                            RoutineName,
    1705           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(Loop).Name,
    1706           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(Loop).ZoneName));
    1707             :                 }
    1708             :             }
    1709           0 :             ShowWarningError(
    1710           0 :                 state, format("{}Remaining surface checks will use \"reordered number of surfaces\", not number of original surfaces", RoutineName));
    1711             :         }
    1712             : 
    1713             :         // Realign the relationship: surface to base surface
    1714       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1715       46044 :             auto &movedSurf = state.dataSurface->Surface(SurfNum);
    1716       46044 :             if (movedSurf.BaseSurf > 0) {
    1717       44408 :                 int newBaseSurfNum = oldToNewSurfNums(movedSurf.BaseSurf);
    1718       44408 :                 movedSurf.BaseSurf = newBaseSurfNum;
    1719             : 
    1720       44408 :                 if (newBaseSurfNum < 1) {
    1721           0 :                     ShowFatalError(
    1722             :                         state,
    1723           0 :                         format("{}Couldn't find the new Surface Number for surface index {} named '{}'. Looking for BaseSurf old index of {}",
    1724             :                                RoutineName,
    1725             :                                SurfNum,
    1726           0 :                                movedSurf.Name,
    1727           0 :                                movedSurf.BaseSurf));
    1728             :                 }
    1729             :             }
    1730       46044 :             auto &reportOrderNum = state.dataSurface->AllSurfaceListReportOrder[SurfNum - 1];
    1731       46044 :             if (reportOrderNum > 0) {
    1732       46044 :                 int newReportOrderNum = oldToNewSurfNums(reportOrderNum);
    1733       46044 :                 reportOrderNum = newReportOrderNum;
    1734             :             }
    1735             :         }
    1736             : 
    1737         796 :         state.dataSurfaceGeometry->SurfaceTmp.deallocate(); // DeAllocate the Temp Surface derived type
    1738             : 
    1739         796 :         createSpaceSurfaceLists(state);
    1740             : 
    1741             :         //  For each Base Surface Type (Wall, Floor, Roof)
    1742             : 
    1743        3184 :         for (const DataSurfaces::SurfaceClass Loop : state.dataSurfaceGeometry->BaseSurfIDs) {
    1744      140520 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    1745             : 
    1746      138132 :                 if (state.dataSurface->Surface(SurfNum).Zone == 0) continue;
    1747             : 
    1748      133224 :                 if (state.dataSurface->Surface(SurfNum).Class != Loop) continue;
    1749             : 
    1750             :                 //  Find all subsurfaces to this surface
    1751     9281884 :                 for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
    1752             : 
    1753     9246572 :                     if (SurfNum == SubSurfNum) continue;
    1754     9211260 :                     if (state.dataSurface->Surface(SubSurfNum).Zone == 0) continue;
    1755     9134418 :                     if (state.dataSurface->Surface(SubSurfNum).BaseSurf != SurfNum) continue;
    1756             : 
    1757             :                     // Check facing angle of Sub compared to base
    1758        6698 :                     checkSubSurfAzTiltNorm(state, state.dataSurface->Surface(SurfNum), state.dataSurface->Surface(SubSurfNum), subSurfaceError);
    1759        6698 :                     if (subSurfaceError) SurfError = true;
    1760             :                 }
    1761             :             }
    1762             :         }
    1763             : 
    1764             :         //**********************************************************************************
    1765             :         // Now, match up interzone surfaces
    1766         796 :         NonMatch = false;
    1767         796 :         izConstDiffMsg = false;
    1768       46840 :         for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    1769             :             //  Clean up Shading Surfaces, make sure they don't go through here.
    1770       46044 :             if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    1771             :             //   If other surface, match it up
    1772             :             //  Both interzone and "internal" surfaces have this pointer set
    1773             :             //  Internal surfaces point to themselves, Interzone to another
    1774       44408 :             if (state.dataSurface->Surface(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    1775       15213 :                 if (not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) {
    1776       15213 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCondName == state.dataSurface->Surface(SurfNum).Name) {
    1777        6286 :                         Found = SurfNum;
    1778             :                     } else {
    1779        8927 :                         Found = Util::FindItemInList(state.dataSurface->Surface(SurfNum).ExtBoundCondName, state.dataSurface->Surface, MovedSurfs);
    1780             :                     }
    1781       15213 :                     if (Found != 0) {
    1782       15213 :                         state.dataSurface->Surface(SurfNum).ExtBoundCond = Found;
    1783             :                         // Check that matching surface is also "OtherZoneSurface"
    1784       24105 :                         if (state.dataSurface->Surface(Found).ExtBoundCond <= 0 &&
    1785        8892 :                             state.dataSurface->Surface(Found).ExtBoundCond != UnreconciledZoneSurface) {
    1786           0 :                             ShowSevereError(state, format("{}Potential \"OtherZoneSurface\" is not matched correctly:", RoutineName));
    1787             : 
    1788           0 :                             ShowContinueError(state,
    1789           0 :                                               format("Surface={}, Zone={}",
    1790           0 :                                                      state.dataSurface->Surface(SurfNum).Name,
    1791           0 :                                                      state.dataSurface->Surface(SurfNum).ZoneName));
    1792           0 :                             ShowContinueError(state,
    1793           0 :                                               format("Nonmatched Other/InterZone Surface={}, Zone={}",
    1794           0 :                                                      state.dataSurface->Surface(Found).Name,
    1795           0 :                                                      state.dataSurface->Surface(Found).ZoneName));
    1796           0 :                             SurfError = true;
    1797             :                         }
    1798             :                         // Check that matching interzone surface has construction with reversed layers
    1799       15213 :                         if (Found != SurfNum) { // Interzone surface
    1800             :                             // Make sure different zones too (CR 4110)
    1801        8927 :                             if (state.dataSurface->Surface(SurfNum).spaceNum == state.dataSurface->Surface(Found).spaceNum) {
    1802           3 :                                 ++state.dataSurfaceGeometry->ErrCount2;
    1803           3 :                                 if (state.dataSurfaceGeometry->ErrCount2 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    1804           4 :                                     ShowWarningError(state,
    1805           4 :                                                      format("{}CAUTION -- Interspace surfaces are occuring in the same space(s).", RoutineName));
    1806           2 :                                     ShowContinueError(
    1807             :                                         state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual occurrences.");
    1808             :                                 }
    1809           3 :                                 if (state.dataGlobal->DisplayExtraWarnings) {
    1810           0 :                                     ShowWarningError(state, format("{}CAUTION -- Interspace surfaces are usually in different spaces", RoutineName));
    1811           0 :                                     ShowContinueError(state,
    1812           0 :                                                       format("Surface={}, Space={}, Zone={}",
    1813           0 :                                                              state.dataSurface->Surface(SurfNum).Name,
    1814           0 :                                                              state.dataHeatBal->space(state.dataSurface->Surface(SurfNum).spaceNum).Name,
    1815           0 :                                                              state.dataSurface->Surface(SurfNum).ZoneName));
    1816           0 :                                     ShowContinueError(state,
    1817           0 :                                                       format("Surface={}, Space={}, Zone={}",
    1818           0 :                                                              state.dataSurface->Surface(Found).Name,
    1819           0 :                                                              state.dataHeatBal->space(state.dataSurface->Surface(Found).spaceNum).Name,
    1820           0 :                                                              state.dataSurface->Surface(Found).ZoneName));
    1821             :                                 }
    1822             :                             }
    1823        8927 :                             ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
    1824        8927 :                             ConstrNumFound = state.dataSurface->Surface(Found).Construction;
    1825        8927 :                             if (ConstrNum <= 0 || ConstrNumFound <= 0) continue;
    1826        8927 :                             if (state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning &&
    1827           0 :                                 state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning)
    1828           0 :                                 continue;
    1829        8939 :                             if (state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning &&
    1830          12 :                                 state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning)
    1831          12 :                                 continue;
    1832        8915 :                             TotLay = state.dataConstruction->Construct(ConstrNum).TotLayers;
    1833        8915 :                             TotLayFound = state.dataConstruction->Construct(ConstrNumFound).TotLayers;
    1834        8915 :                             if (TotLay != TotLayFound) { // Different number of layers
    1835             :                                 // match on like Uvalues (nominal)
    1836           0 :                                 if (std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound)) > 0.001) {
    1837           0 :                                     ShowSevereError(state,
    1838           0 :                                                     format("{}Construction {} of interzone surface {} does not have the same number of layers as the "
    1839             :                                                            "construction {} of adjacent surface {}",
    1840             :                                                            RoutineName,
    1841           0 :                                                            state.dataConstruction->Construct(ConstrNum).Name,
    1842           0 :                                                            state.dataSurface->Surface(SurfNum).Name,
    1843           0 :                                                            state.dataConstruction->Construct(ConstrNumFound).Name,
    1844           0 :                                                            state.dataSurface->Surface(Found).Name));
    1845           0 :                                     if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning ||
    1846           0 :                                         !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning) {
    1847           0 :                                         ShowContinueError(state, "...this problem for this pair will not be reported again.");
    1848           0 :                                         state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning = true;
    1849           0 :                                         state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning = true;
    1850             :                                     }
    1851           0 :                                     SurfError = true;
    1852             :                                 }
    1853             :                             } else { // Same number of layers; check for reverse layers
    1854             :                                 // check layers as number of layers is the same
    1855        8915 :                                 izConstDiff = false;
    1856             :                                 // ok if same nominal U
    1857        8915 :                                 CheckForReversedLayers(state, izConstDiff, ConstrNum, ConstrNumFound, TotLay);
    1858        8917 :                                 if (izConstDiff &&
    1859           2 :                                     std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound)) > 0.001) {
    1860           0 :                                     ShowSevereError(state,
    1861           0 :                                                     format("{}Construction {} of interzone surface {} does not have the same materials in the "
    1862             :                                                            "reverse order as the construction {} of adjacent surface {}",
    1863             :                                                            RoutineName,
    1864           0 :                                                            state.dataConstruction->Construct(ConstrNum).Name,
    1865           0 :                                                            state.dataSurface->Surface(SurfNum).Name,
    1866           0 :                                                            state.dataConstruction->Construct(ConstrNumFound).Name,
    1867           0 :                                                            state.dataSurface->Surface(Found).Name));
    1868           0 :                                     ShowContinueError(state,
    1869             :                                                       "or the properties of the reversed layers are not correct due to differing layer front and "
    1870             :                                                       "back side values");
    1871           0 :                                     if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning ||
    1872           0 :                                         !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning) {
    1873           0 :                                         ShowContinueError(state, "...this problem for this pair will not be reported again.");
    1874           0 :                                         state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning = true;
    1875           0 :                                         state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning = true;
    1876             :                                     }
    1877           0 :                                     SurfError = true;
    1878        8915 :                                 } else if (izConstDiff) {
    1879           4 :                                     ShowWarningError(state,
    1880           4 :                                                      format("{}Construction {} of interzone surface {} does not have the same materials in the "
    1881             :                                                             "reverse order as the construction {} of adjacent surface {}",
    1882             :                                                             RoutineName,
    1883           2 :                                                             state.dataConstruction->Construct(ConstrNum).Name,
    1884           2 :                                                             state.dataSurface->Surface(SurfNum).Name,
    1885           2 :                                                             state.dataConstruction->Construct(ConstrNumFound).Name,
    1886           2 :                                                             state.dataSurface->Surface(Found).Name));
    1887           2 :                                     ShowContinueError(state,
    1888             :                                                       "or the properties of the reversed layers are not correct due to differing layer front and "
    1889             :                                                       "back side values");
    1890           4 :                                     ShowContinueError(
    1891             :                                         state,
    1892           4 :                                         format("...but Nominal U values are similar, diff=[{:.4R}] ... simulation proceeds.",
    1893           2 :                                                std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound))));
    1894           2 :                                     if (!izConstDiffMsg) {
    1895           2 :                                         ShowContinueError(state,
    1896             :                                                           "...if the two zones are expected to have significantly different temperatures, the proper "
    1897             :                                                           "\"reverse\" construction should be created.");
    1898           2 :                                         izConstDiffMsg = true;
    1899             :                                     }
    1900           2 :                                     if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning ||
    1901           0 :                                         !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning) {
    1902           2 :                                         ShowContinueError(state, "...this problem for this pair will not be reported again.");
    1903           2 :                                         state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning = true;
    1904           2 :                                         state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning = true;
    1905             :                                     }
    1906             :                                 }
    1907             :                             }
    1908             : 
    1909             :                             // If significantly different areas -- this would not be good
    1910        8915 :                             MultFound = state.dataHeatBal->Zone(state.dataSurface->Surface(Found).Zone).Multiplier *
    1911        8915 :                                         state.dataHeatBal->Zone(state.dataSurface->Surface(Found).Zone).ListMultiplier;
    1912        8915 :                             MultSurfNum = state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).Multiplier *
    1913        8915 :                                           state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).ListMultiplier;
    1914        8915 :                             if (state.dataSurface->Surface(Found).Area > 0.0) {
    1915        8915 :                                 if (std::abs((state.dataSurface->Surface(Found).Area * MultFound -
    1916        8915 :                                               state.dataSurface->Surface(SurfNum).Area * MultSurfNum) /
    1917        8915 :                                              state.dataSurface->Surface(Found).Area * MultFound) > 0.02) { // 2% difference in areas
    1918           0 :                                     ++state.dataSurfaceGeometry->ErrCount4;
    1919           0 :                                     if (state.dataSurfaceGeometry->ErrCount4 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    1920           0 :                                         ShowWarningError(
    1921             :                                             state,
    1922           0 :                                             format("{}InterZone Surface Areas do not match as expected and might not satisfy conservation of energy:",
    1923             :                                                    RoutineName));
    1924           0 :                                         ShowContinueError(
    1925             :                                             state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual mismatches.");
    1926             :                                     }
    1927           0 :                                     if (state.dataGlobal->DisplayExtraWarnings) {
    1928           0 :                                         ShowWarningError(
    1929             :                                             state,
    1930           0 :                                             format("{}InterZone Surface Areas do not match as expected and might not satisfy conservation of energy:",
    1931             :                                                    RoutineName));
    1932             : 
    1933           0 :                                         if (MultFound == 1 && MultSurfNum == 1) {
    1934           0 :                                             ShowContinueError(state,
    1935           0 :                                                               format("  Area={:.1T} in Surface={}, Zone={}",
    1936           0 :                                                                      state.dataSurface->Surface(SurfNum).Area,
    1937           0 :                                                                      state.dataSurface->Surface(SurfNum).Name,
    1938           0 :                                                                      state.dataSurface->Surface(SurfNum).ZoneName));
    1939           0 :                                             ShowContinueError(state,
    1940           0 :                                                               format("  Area={:.1T} in Surface={}, Zone={}",
    1941           0 :                                                                      state.dataSurface->Surface(Found).Area,
    1942           0 :                                                                      state.dataSurface->Surface(Found).Name,
    1943           0 :                                                                      state.dataSurface->Surface(Found).ZoneName));
    1944             :                                         } else { // Show multiplier info
    1945           0 :                                             ShowContinueError(state,
    1946           0 :                                                               format("  Area={:.1T}, Multipliers={}, Total Area={:.1T} in Surface={} Zone={}",
    1947           0 :                                                                      state.dataSurface->Surface(SurfNum).Area,
    1948             :                                                                      MultSurfNum,
    1949           0 :                                                                      state.dataSurface->Surface(SurfNum).Area * MultSurfNum,
    1950           0 :                                                                      state.dataSurface->Surface(SurfNum).Name,
    1951           0 :                                                                      state.dataSurface->Surface(SurfNum).ZoneName));
    1952             : 
    1953           0 :                                             ShowContinueError(state,
    1954           0 :                                                               format("  Area={:.1T}, Multipliers={}, Total Area={:.1T} in Surface={} Zone={}",
    1955           0 :                                                                      state.dataSurface->Surface(Found).Area,
    1956             :                                                                      MultFound,
    1957           0 :                                                                      state.dataSurface->Surface(Found).Area * MultFound,
    1958           0 :                                                                      state.dataSurface->Surface(Found).Name,
    1959           0 :                                                                      state.dataSurface->Surface(Found).ZoneName));
    1960             :                                         }
    1961             :                                     }
    1962             :                                 }
    1963             :                             }
    1964             :                             // Check opposites Azimuth and Tilt
    1965             :                             // Tilt
    1966        8915 :                             if (std::abs(std::abs(state.dataSurface->Surface(Found).Tilt + state.dataSurface->Surface(SurfNum).Tilt) - 180.0) > 1.0) {
    1967           0 :                                 ShowWarningError(state, format("{}InterZone Surface Tilts do not match as expected.", RoutineName));
    1968           0 :                                 ShowContinueError(state,
    1969           0 :                                                   format("  Tilt={:.1T} in Surface={}, Zone={}",
    1970           0 :                                                          state.dataSurface->Surface(SurfNum).Tilt,
    1971           0 :                                                          state.dataSurface->Surface(SurfNum).Name,
    1972           0 :                                                          state.dataSurface->Surface(SurfNum).ZoneName));
    1973           0 :                                 ShowContinueError(state,
    1974           0 :                                                   format("  Tilt={:.1T} in Surface={}, Zone={}",
    1975           0 :                                                          state.dataSurface->Surface(Found).Tilt,
    1976           0 :                                                          state.dataSurface->Surface(Found).Name,
    1977           0 :                                                          state.dataSurface->Surface(Found).ZoneName));
    1978             :                             }
    1979             :                             // check surface class match.  interzone surface.
    1980             : 
    1981        8915 :                             if ((state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Wall &&
    1982       17830 :                                  state.dataSurface->Surface(Found).Class != SurfaceClass::Wall) ||
    1983        8915 :                                 (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall &&
    1984        3039 :                                  state.dataSurface->Surface(Found).Class == SurfaceClass::Wall)) {
    1985           0 :                                 ShowWarningError(state, format("{}InterZone Surface Classes do not match as expected.", RoutineName));
    1986           0 :                                 ShowContinueError(state,
    1987           0 :                                                   format("Surface=\"{}\", surface class={}",
    1988           0 :                                                          state.dataSurface->Surface(SurfNum).Name,
    1989           0 :                                                          cSurfaceClass(state.dataSurface->Surface(SurfNum).Class)));
    1990           0 :                                 ShowContinueError(state,
    1991           0 :                                                   format("Adjacent Surface=\"{}\", surface class={}",
    1992           0 :                                                          state.dataSurface->Surface(Found).Name,
    1993           0 :                                                          cSurfaceClass(state.dataSurface->Surface(Found).Class)));
    1994           0 :                                 ShowContinueError(state, "Other errors/warnings may follow about these surfaces.");
    1995             :                             }
    1996        8915 :                             if ((state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Roof &&
    1997       17830 :                                  state.dataSurface->Surface(Found).Class != SurfaceClass::Floor) ||
    1998        8915 :                                 (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof &&
    1999        7442 :                                  state.dataSurface->Surface(Found).Class == SurfaceClass::Floor)) {
    2000           0 :                                 ShowWarningError(state, format("{}InterZone Surface Classes do not match as expected.", RoutineName));
    2001           0 :                                 ShowContinueError(state,
    2002           0 :                                                   format("Surface=\"{}\", surface class={}",
    2003           0 :                                                          state.dataSurface->Surface(SurfNum).Name,
    2004           0 :                                                          cSurfaceClass(state.dataSurface->Surface(SurfNum).Class)));
    2005           0 :                                 ShowContinueError(state,
    2006           0 :                                                   format("Adjacent Surface=\"{}\", surface class={}",
    2007           0 :                                                          state.dataSurface->Surface(Found).Name,
    2008           0 :                                                          cSurfaceClass(state.dataSurface->Surface(Found).Class)));
    2009           0 :                                 ShowContinueError(state, "Other errors/warnings may follow about these surfaces.");
    2010             :                             }
    2011       16357 :                             if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof &&
    2012        7442 :                                 state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) {
    2013             :                                 // Walls, Windows, Doors, Glass Doors
    2014        5916 :                                 if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) {
    2015             :                                     // Surface is a Door, Window or Glass Door
    2016          40 :                                     if (state.dataSurface->Surface(SurfNum).BaseSurf == 0) continue; // error detected elsewhere
    2017          79 :                                     if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Class == SurfaceClass::Roof ||
    2018          39 :                                         state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Class == SurfaceClass::Floor)
    2019           2 :                                         continue;
    2020             :                                 }
    2021        5914 :                                 if (std::abs(std::abs(state.dataSurface->Surface(SurfNum).Azimuth - state.dataSurface->Surface(Found).Azimuth) -
    2022        5914 :                                              180.0) > 1.0) {
    2023           0 :                                     if (std::abs(state.dataSurface->Surface(SurfNum).SinTilt) > 0.5 || state.dataGlobal->DisplayExtraWarnings) {
    2024             :                                         // if horizontal surfaces, then these are windows/doors/etc in those items.
    2025           0 :                                         ShowWarningError(state, format("{}InterZone Surface Azimuths do not match as expected.", RoutineName));
    2026           0 :                                         ShowContinueError(state,
    2027           0 :                                                           format("  Azimuth={:.1T}, Tilt={:.1T}, in Surface={}, Zone={}",
    2028           0 :                                                                  state.dataSurface->Surface(SurfNum).Azimuth,
    2029           0 :                                                                  state.dataSurface->Surface(SurfNum).Tilt,
    2030           0 :                                                                  state.dataSurface->Surface(SurfNum).Name,
    2031           0 :                                                                  state.dataSurface->Surface(SurfNum).ZoneName));
    2032           0 :                                         ShowContinueError(state,
    2033           0 :                                                           format("  Azimuth={:.1T}, Tilt={:.1T}, in Surface={}, Zone={}",
    2034           0 :                                                                  state.dataSurface->Surface(Found).Azimuth,
    2035           0 :                                                                  state.dataSurface->Surface(Found).Tilt,
    2036           0 :                                                                  state.dataSurface->Surface(Found).Name,
    2037           0 :                                                                  state.dataSurface->Surface(Found).ZoneName));
    2038           0 :                                         ShowContinueError(
    2039             :                                             state,
    2040           0 :                                             format("..surface class of first surface={}", cSurfaceClass(state.dataSurface->Surface(SurfNum).Class)));
    2041           0 :                                         ShowContinueError(
    2042             :                                             state,
    2043           0 :                                             format("..surface class of second surface={}", cSurfaceClass(state.dataSurface->Surface(Found).Class)));
    2044             :                                     }
    2045             :                                 }
    2046             :                             }
    2047             : 
    2048             :                             // Make sure exposures (Sun, Wind) are the same.....and are "not"
    2049        8913 :                             if (state.dataSurface->Surface(SurfNum).ExtSolar || state.dataSurface->Surface(Found).ExtSolar) {
    2050           0 :                                 ShowWarningError(state, format("{}Interzone surfaces cannot be \"SunExposed\" -- removing SunExposed", RoutineName));
    2051           0 :                                 ShowContinueError(state,
    2052           0 :                                                   format("  Surface={}, Zone={}",
    2053           0 :                                                          state.dataSurface->Surface(SurfNum).Name,
    2054           0 :                                                          state.dataSurface->Surface(SurfNum).ZoneName));
    2055           0 :                                 ShowContinueError(state,
    2056           0 :                                                   format("  Surface={}, Zone={}",
    2057           0 :                                                          state.dataSurface->Surface(Found).Name,
    2058           0 :                                                          state.dataSurface->Surface(Found).ZoneName));
    2059           0 :                                 state.dataSurface->Surface(SurfNum).ExtSolar = false;
    2060           0 :                                 state.dataSurface->Surface(Found).ExtSolar = false;
    2061             :                             }
    2062        8913 :                             if (state.dataSurface->Surface(SurfNum).ExtWind || state.dataSurface->Surface(Found).ExtWind) {
    2063           0 :                                 ShowWarningError(state,
    2064           0 :                                                  format("{}Interzone surfaces cannot be \"WindExposed\" -- removing WindExposed", RoutineName));
    2065           0 :                                 ShowContinueError(state,
    2066           0 :                                                   format("  Surface={}, Zone={}",
    2067           0 :                                                          state.dataSurface->Surface(SurfNum).Name,
    2068           0 :                                                          state.dataSurface->Surface(SurfNum).ZoneName));
    2069           0 :                                 ShowContinueError(state,
    2070           0 :                                                   format("  Surface={}, Zone={}",
    2071           0 :                                                          state.dataSurface->Surface(Found).Name,
    2072           0 :                                                          state.dataSurface->Surface(Found).ZoneName));
    2073           0 :                                 state.dataSurface->Surface(SurfNum).ExtWind = false;
    2074           0 :                                 state.dataSurface->Surface(Found).ExtWind = false;
    2075             :                             }
    2076             :                         }
    2077             :                         // Set opposing surface back to this one (regardless of error)
    2078       15199 :                         state.dataSurface->Surface(Found).ExtBoundCond = SurfNum;
    2079             :                         // Check subsurfaces...  make sure base surface is also an interzone surface
    2080       15199 :                         if (state.dataSurface->Surface(SurfNum).BaseSurf != SurfNum) { // Subsurface
    2081          76 :                             if ((state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) &&
    2082          38 :                                 not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) {
    2083             :                                 // if not internal subsurface
    2084          38 :                                 if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond ==
    2085          38 :                                     state.dataSurface->Surface(SurfNum).BaseSurf) {
    2086             :                                     // base surface is not interzone surface
    2087           0 :                                     ShowSevereError(state,
    2088           0 :                                                     format("{}SubSurface=\"{}\" is an interzone subsurface.",
    2089             :                                                            RoutineName,
    2090           0 :                                                            state.dataSurface->Surface(SurfNum).Name));
    2091           0 :                                     ShowContinueError(state,
    2092           0 :                                                       format("..but the Base Surface is not an interzone surface, Surface=\"{}\".",
    2093           0 :                                                              state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name));
    2094           0 :                                     SurfError = true;
    2095             :                                 }
    2096             :                             }
    2097             :                         }
    2098             :                     } else {
    2099             :                         //  Seems unlikely that an internal surface would be missing itself, so this message
    2100             :                         //  only indicates for adjacent (interzone) surfaces.
    2101           0 :                         ShowSevereError(state,
    2102           0 :                                         format("{}Adjacent Surface not found: {} adjacent to surface {}",
    2103             :                                                RoutineName,
    2104           0 :                                                state.dataSurface->Surface(SurfNum).ExtBoundCondName,
    2105           0 :                                                state.dataSurface->Surface(SurfNum).Name));
    2106           0 :                         NonMatch = true;
    2107           0 :                         SurfError = true;
    2108             :                     }
    2109           0 :                 } else if (state.dataSurface->Surface(SurfNum).BaseSurf != SurfNum) { // Subsurface
    2110           0 :                     if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond > 0 &&
    2111           0 :                         state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond !=
    2112           0 :                             state.dataSurface->Surface(SurfNum).BaseSurf) { // If Interzone surface, subsurface must be also.
    2113           0 :                         ShowSevereError(state, format("{}SubSurface on Interzone Surface must be an Interzone SubSurface.", RoutineName));
    2114           0 :                         ShowContinueError(state,
    2115           0 :                                           format("...OutsideFaceEnvironment is blank, in Surface={}", state.dataSurface->Surface(SurfNum).Name));
    2116           0 :                         SurfError = true;
    2117             :                     } else {
    2118           0 :                         ++state.dataSurfaceGeometry->ErrCount3;
    2119           0 :                         if (state.dataSurfaceGeometry->ErrCount3 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2120           0 :                             ShowWarningError(state, format("{}Blank name for Outside Boundary Condition Objects.", RoutineName));
    2121           0 :                             ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
    2122             :                         }
    2123           0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    2124           0 :                             ShowWarningError(state,
    2125           0 :                                              format("{}Blank name for Outside Boundary Condition Object, in surface={}",
    2126             :                                                     RoutineName,
    2127           0 :                                                     state.dataSurface->Surface(SurfNum).Name));
    2128           0 :                             ShowContinueError(state,
    2129           0 :                                               format("Resetting this surface to be an internal zone surface, zone={}",
    2130           0 :                                                      state.dataSurface->Surface(SurfNum).ZoneName));
    2131             :                         }
    2132           0 :                         state.dataSurface->Surface(SurfNum).ExtBoundCondName = state.dataSurface->Surface(SurfNum).Name;
    2133           0 :                         state.dataSurface->Surface(SurfNum).ExtBoundCond = SurfNum;
    2134             :                     }
    2135             :                 } else {
    2136           0 :                     ++state.dataSurfaceGeometry->ErrCount3;
    2137           0 :                     if (state.dataSurfaceGeometry->ErrCount3 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2138           0 :                         ShowSevereError(state, format("{}Blank name for Outside Boundary Condition Objects.", RoutineName));
    2139           0 :                         ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
    2140             :                     }
    2141           0 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    2142           0 :                         ShowWarningError(state,
    2143           0 :                                          format("{}Blank name for Outside Boundary Condition Object, in surface={}",
    2144             :                                                 RoutineName,
    2145           0 :                                                 state.dataSurface->Surface(SurfNum).Name));
    2146           0 :                         ShowContinueError(state,
    2147           0 :                                           format("Resetting this surface to be an internal zone (adiabatic) surface, zone={}",
    2148           0 :                                                  state.dataSurface->Surface(SurfNum).ZoneName));
    2149             :                     }
    2150           0 :                     state.dataSurface->Surface(SurfNum).ExtBoundCondName = state.dataSurface->Surface(SurfNum).Name;
    2151           0 :                     state.dataSurface->Surface(SurfNum).ExtBoundCond = SurfNum;
    2152           0 :                     SurfError = true;
    2153             :                 }
    2154             :             }
    2155             : 
    2156             :         } // ...end of the Surface DO loop for finding BaseSurf
    2157         796 :         if (NonMatch) {
    2158           0 :             ShowSevereError(state, format("{}Non matching interzone surfaces found", RoutineName));
    2159             :         }
    2160             : 
    2161             :         //**********************************************************************************
    2162             :         // Warn about interzone surfaces that have adiabatic windows/vice versa
    2163         796 :         SubSurfaceSevereDisplayed = false;
    2164       46840 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2165       46044 :             if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    2166       44408 :             if (state.dataSurface->Surface(SurfNum).BaseSurf == SurfNum) continue; // base surface
    2167             :             // not base surface.  Check it.
    2168        6698 :             if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond <= 0) { // exterior or other base surface
    2169        6618 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond !=
    2170        6618 :                     state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) { // should match base surface
    2171           0 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCond == SurfNum) {
    2172           0 :                         ShowSevereError(
    2173             :                             state,
    2174           0 :                             format("{}Subsurface=\"{}\" exterior condition [adiabatic surface] in a base surface=\"{}\" with exterior condition [{}]",
    2175             :                                    RoutineName,
    2176           0 :                                    state.dataSurface->Surface(SurfNum).Name,
    2177           0 :                                    state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name,
    2178           0 :                                    cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond)));
    2179           0 :                         SurfError = true;
    2180           0 :                     } else if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) {
    2181           0 :                         ShowSevereError(
    2182             :                             state,
    2183           0 :                             format("{}Subsurface=\"{}\" exterior condition [interzone surface] in a base surface=\"{}\" with exterior condition [{}]",
    2184             :                                    RoutineName,
    2185           0 :                                    state.dataSurface->Surface(SurfNum).Name,
    2186           0 :                                    state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name,
    2187           0 :                                    cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond)));
    2188           0 :                         SurfError = true;
    2189           0 :                     } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond == OtherSideCondModeledExt) {
    2190           0 :                         ShowWarningError(
    2191             :                             state,
    2192           0 :                             format("{}Subsurface=\"{}\" exterior condition [{}] in a base surface=\"{}\" with exterior condition [{}]",
    2193             :                                    RoutineName,
    2194           0 :                                    state.dataSurface->Surface(SurfNum).Name,
    2195           0 :                                    cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond),
    2196           0 :                                    state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name,
    2197           0 :                                    cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond)));
    2198           0 :                         ShowContinueError(state, "...SubSurface will not use the exterior condition model of the base surface.");
    2199             :                     } else {
    2200           0 :                         ShowSevereError(
    2201             :                             state,
    2202           0 :                             format("{}Subsurface=\"{}\" exterior condition [{}] in a base surface=\"{}\" with exterior condition [{}]",
    2203             :                                    RoutineName,
    2204           0 :                                    state.dataSurface->Surface(SurfNum).Name,
    2205           0 :                                    cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond),
    2206           0 :                                    state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name,
    2207           0 :                                    cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond)));
    2208           0 :                         SurfError = true;
    2209             :                     }
    2210           0 :                     if (!SubSurfaceSevereDisplayed && SurfError) {
    2211           0 :                         ShowContinueError(state, "...calculations for heat balance would be compromised.");
    2212           0 :                         SubSurfaceSevereDisplayed = true;
    2213             :                     }
    2214             :                 }
    2215          80 :             } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).BaseSurf ==
    2216          80 :                        state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) {
    2217             :                 // adiabatic surface. make sure subsurfaces match
    2218           0 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) { // not adiabatic surface
    2219           0 :                     if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) {
    2220           0 :                         ShowSevereError(state,
    2221           0 :                                         format("{}Subsurface=\"{}\" exterior condition [interzone surface] in a base surface=\"{}\" with exterior "
    2222             :                                                "condition [adiabatic surface]",
    2223             :                                                RoutineName,
    2224           0 :                                                state.dataSurface->Surface(SurfNum).Name,
    2225           0 :                                                state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name));
    2226             :                     } else {
    2227           0 :                         ShowSevereError(
    2228             :                             state,
    2229           0 :                             format("{}Subsurface=\"{}\" exterior condition [{}] in a base surface=\"{}\" with exterior condition [adiabatic surface]",
    2230             :                                    RoutineName,
    2231           0 :                                    state.dataSurface->Surface(SurfNum).Name,
    2232           0 :                                    cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond),
    2233           0 :                                    state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name));
    2234             :                     }
    2235           0 :                     if (!SubSurfaceSevereDisplayed) {
    2236           0 :                         ShowContinueError(state, "...calculations for heat balance would be compromised.");
    2237           0 :                         SubSurfaceSevereDisplayed = true;
    2238             :                     }
    2239           0 :                     SurfError = true;
    2240             :                 }
    2241          80 :             } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond > 0) { // interzone surface
    2242          80 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond == SurfNum) {
    2243           0 :                     ShowSevereError(state,
    2244           0 :                                     format("{}Subsurface=\"{}\" is an adiabatic surface in an Interzone base surface=\"{}\"",
    2245             :                                            RoutineName,
    2246           0 :                                            state.dataSurface->Surface(SurfNum).Name,
    2247           0 :                                            state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name));
    2248           0 :                     if (!SubSurfaceSevereDisplayed) {
    2249           0 :                         ShowContinueError(state, "...calculations for heat balance would be compromised.");
    2250           0 :                         SubSurfaceSevereDisplayed = true;
    2251             :                     }
    2252             :                     //        SurfError=.TRUE.
    2253             :                 }
    2254             :             }
    2255             :         }
    2256             : 
    2257         796 :         setSurfaceFirstLast(state);
    2258             : 
    2259             :         // Set up Floor Areas for Zones and Spaces
    2260         796 :         Real64 constexpr floorAreaTolerance(0.05);
    2261         796 :         Real64 constexpr floorAreaPercentTolerance(floorAreaTolerance * 100.0);
    2262         796 :         if (!SurfError) {
    2263        5852 :             for (auto &thisZone : state.dataHeatBal->Zone) {
    2264       10124 :                 for (int spaceNum : thisZone.spaceIndexes) {
    2265        5068 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2266       49458 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    2267       44390 :                         auto &thisSurf = state.dataSurface->Surface(SurfNum);
    2268       44390 :                         if (thisSurf.Class == SurfaceClass::Floor) {
    2269        6890 :                             thisZone.HasFloor = true;
    2270        6890 :                             thisSpace.hasFloor = true;
    2271        6890 :                             thisSpace.calcFloorArea += thisSurf.Area;
    2272             :                         }
    2273       44390 :                         if (thisSurf.Class == SurfaceClass::Roof) {
    2274        5801 :                             thisZone.CeilingArea += thisSurf.Area;
    2275        5801 :                             thisZone.HasRoof = true;
    2276             :                         }
    2277             :                     }
    2278        5056 :                 }
    2279         796 :             }
    2280         796 :             ErrCount = 0;
    2281        5877 :             for (auto &thisSpace : state.dataHeatBal->space) {
    2282        5081 :                 if (thisSpace.userEnteredFloorArea != Constant::AutoCalculate) {
    2283             :                     // Check entered vs calculated
    2284           0 :                     if (thisSpace.userEnteredFloorArea > 0.0) { // User entered Space floor area,
    2285             :                         // produce message if not near calculated
    2286           0 :                         if (thisSpace.calcFloorArea > 0.0) {
    2287           0 :                             Real64 diffp = std::abs(thisSpace.calcFloorArea - thisSpace.userEnteredFloorArea) / thisSpace.userEnteredFloorArea;
    2288           0 :                             if (diffp > floorAreaTolerance) {
    2289           0 :                                 ++ErrCount;
    2290           0 :                                 if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2291           0 :                                     ShowWarningError(
    2292             :                                         state,
    2293           0 :                                         format("{}Entered Space Floor Area(s) differ more than {:.0R}% from calculated Space Floor Area(s).",
    2294           0 :                                                std::string(RoutineName),
    2295             :                                                floorAreaPercentTolerance));
    2296           0 :                                     ShowContinueError(state,
    2297             :                                                       "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual Spaces.");
    2298             :                                 }
    2299           0 :                                 if (state.dataGlobal->DisplayExtraWarnings) {
    2300             :                                     // Warn user of using specified Space Floor Area
    2301           0 :                                     ShowWarningError(
    2302             :                                         state,
    2303           0 :                                         format("{}Entered Floor Area for Space=\"{}\" is {:.1R}% different from the calculated Floor Area.",
    2304           0 :                                                std::string(RoutineName),
    2305           0 :                                                thisSpace.Name,
    2306           0 :                                                diffp * 100.0));
    2307           0 :                                     ShowContinueError(state,
    2308           0 :                                                       format("Entered Space Floor Area={:.2R}, Calculated Space Floor Area={:.2R}, entered "
    2309             :                                                              "Floor Area will be used.",
    2310           0 :                                                              thisSpace.userEnteredFloorArea,
    2311           0 :                                                              thisSpace.calcFloorArea));
    2312             :                                 }
    2313             :                             }
    2314             :                         }
    2315           0 :                         thisSpace.FloorArea = thisSpace.userEnteredFloorArea;
    2316           0 :                         thisSpace.hasFloor = true;
    2317             :                     }
    2318             :                 } else {
    2319        5081 :                     thisSpace.FloorArea = thisSpace.calcFloorArea;
    2320             :                 }
    2321         796 :             }
    2322         796 :             ErrCount = 0;
    2323        5852 :             for (auto &thisZone : state.dataHeatBal->Zone) {
    2324             :                 // Calculate zone floor area as sum of space floor areas
    2325       10124 :                 for (int spaceNum : thisZone.spaceIndexes) {
    2326        5068 :                     thisZone.CalcFloorArea += state.dataHeatBal->space(spaceNum).FloorArea;
    2327        5068 :                     thisZone.HasFloor |= state.dataHeatBal->space(spaceNum).hasFloor;
    2328        5056 :                 }
    2329        5056 :                 if (thisZone.UserEnteredFloorArea != Constant::AutoCalculate) {
    2330             :                     // Check entered vs calculated
    2331           4 :                     if (thisZone.UserEnteredFloorArea > 0.0) { // User entered zone floor area,
    2332             :                         // produce message if not near calculated
    2333           4 :                         if (thisZone.CalcFloorArea > 0.0) {
    2334           4 :                             Real64 diffp = std::abs(thisZone.CalcFloorArea - thisZone.UserEnteredFloorArea) / thisZone.UserEnteredFloorArea;
    2335           4 :                             if (diffp > 0.05) {
    2336           1 :                                 ++ErrCount;
    2337           1 :                                 if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    2338           2 :                                     ShowWarningError(
    2339             :                                         state,
    2340           2 :                                         format("{}Entered Zone Floor Area(s) differ more than {:.0R}% from the sum of the Space Floor Area(s).",
    2341           2 :                                                std::string(RoutineName),
    2342             :                                                floorAreaPercentTolerance));
    2343           1 :                                     ShowContinueError(state,
    2344             :                                                       "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
    2345             :                                 }
    2346           1 :                                 if (state.dataGlobal->DisplayExtraWarnings) {
    2347             :                                     // Warn user of using specified Zone Floor Area
    2348           0 :                                     ShowWarningError(state,
    2349           0 :                                                      format("{}Entered Floor Area for Zone=\"{}\" is {:.1R}% different from the sum of the "
    2350             :                                                             "Space Floor Area(s).",
    2351           0 :                                                             std::string(RoutineName),
    2352           0 :                                                             thisZone.Name,
    2353           0 :                                                             diffp * 100.0));
    2354           0 :                                     ShowContinueError(state,
    2355           0 :                                                       format("Entered Zone Floor Area={:.2R}, Sum of Space Floor Area(s)={:.2R}",
    2356           0 :                                                              thisZone.UserEnteredFloorArea,
    2357           0 :                                                              thisZone.CalcFloorArea));
    2358           0 :                                     ShowContinueError(
    2359             :                                         state, "Entered Zone Floor Area will be used and Space Floor Area(s) will be adjusted proportionately.");
    2360             :                                 }
    2361             :                             }
    2362             :                         }
    2363           4 :                         thisZone.FloorArea = thisZone.UserEnteredFloorArea;
    2364           4 :                         thisZone.HasFloor = true;
    2365             : 
    2366             :                         // Adjust space floor areas to match zone floor area
    2367           4 :                         if (thisZone.numSpaces == 1) {
    2368             :                             // If the zone contains only one space, then set the Space area to the Zone area
    2369           4 :                             int spaceNum = thisZone.spaceIndexes(1);
    2370           4 :                             state.dataHeatBal->space(spaceNum).FloorArea = thisZone.FloorArea;
    2371           0 :                         } else if (thisZone.CalcFloorArea > 0.0) {
    2372             :                             // Adjust space areas proportionately
    2373           0 :                             Real64 areaRatio = thisZone.FloorArea / thisZone.CalcFloorArea;
    2374           0 :                             for (int spaceNum : thisZone.spaceIndexes) {
    2375           0 :                                 state.dataHeatBal->space(spaceNum).FloorArea *= areaRatio;
    2376           0 :                             }
    2377             :                         } else {
    2378           0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    2379             :                                 // Warn if calculated floor area was zero and there is more than one Space
    2380           0 :                                 ShowWarningError(
    2381             :                                     state,
    2382           0 :                                     format("{}Entered Floor Area entered for Zone=\"{}\" significantly different from sum of Space Floor Areas",
    2383             :                                            RoutineName,
    2384           0 :                                            thisZone.Name));
    2385           0 :                                 ShowContinueError(state,
    2386             :                                                   "But the sum of the Space Floor Areas is zero and there is more than one Space in the zone."
    2387             :                                                   "Unable to apportion the zone floor area. Space Floor Areas are zero.");
    2388             :                             }
    2389             :                         }
    2390             :                     } else {
    2391           0 :                         if (thisZone.CalcFloorArea > 0.0) thisZone.FloorArea = thisZone.CalcFloorArea;
    2392             :                     }
    2393             :                 } else {
    2394        5052 :                     thisZone.FloorArea = thisZone.CalcFloorArea;
    2395             :                 }
    2396        5056 :                 Real64 totSpacesFloorArea = 0.0;
    2397       10124 :                 for (int spaceNum : thisZone.spaceIndexes) {
    2398        5068 :                     totSpacesFloorArea += state.dataHeatBal->space(spaceNum).FloorArea;
    2399        5056 :                 }
    2400        5056 :                 if (totSpacesFloorArea > 0.0) {
    2401       10120 :                     for (int spaceNum : thisZone.spaceIndexes) {
    2402        5066 :                         state.dataHeatBal->space(spaceNum).fracZoneFloorArea = state.dataHeatBal->space(spaceNum).FloorArea / totSpacesFloorArea;
    2403        5054 :                     }
    2404             :                 } // else leave fractions at zero
    2405         796 :             }
    2406             :         }
    2407             : 
    2408       46840 :         for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2409       46044 :             if (state.dataSurface->Surface(SurfNum).Area < 1.e-06) {
    2410           0 :                 ShowSevereError(state,
    2411           0 :                                 format("{}Zero or negative surface area[{:.5R}], Surface={}",
    2412             :                                        RoutineName,
    2413           0 :                                        state.dataSurface->Surface(SurfNum).Area,
    2414           0 :                                        state.dataSurface->Surface(SurfNum).Name));
    2415           0 :                 SurfError = true;
    2416             :             }
    2417       46044 :             if (state.dataSurface->Surface(SurfNum).Area >= 1.e-06 && state.dataSurface->Surface(SurfNum).Area < 0.001) {
    2418           0 :                 ShowWarningError(state,
    2419           0 :                                  format("{}Very small surface area[{:.5R}], Surface={}",
    2420             :                                         RoutineName,
    2421           0 :                                         state.dataSurface->Surface(SurfNum).Area,
    2422           0 :                                         state.dataSurface->Surface(SurfNum).Name));
    2423             :             }
    2424             :         }
    2425             : 
    2426       46840 :         for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2427       46044 :             auto &surf = state.dataSurface->Surface(SurfNum);
    2428             :             // GLASSDOORs and TDD:DIFFUSERs will be treated as windows in the subsequent heat transfer and daylighting
    2429             :             // calculations. Reset class to 'Window' after saving the original designation in SurfaceWindow.
    2430             : 
    2431       46044 :             surf.OriginalClass = surf.Class;
    2432             : 
    2433       46044 :             if (surf.Class == SurfaceClass::GlassDoor || surf.Class == SurfaceClass::TDD_Diffuser) surf.Class = SurfaceClass::Window;
    2434             : 
    2435       46044 :             if (surf.Class == SurfaceClass::TDD_Dome) {
    2436             :                 // Reset the TDD:DOME subsurface to act as a base surface that can shade and be shaded
    2437             :                 // NOTE: This must be set early so that subsequent shading calculations are done correctly
    2438           2 :                 surf.BaseSurf = SurfNum;
    2439             :             }
    2440             :         }
    2441             : 
    2442         796 :         errFlag = false;
    2443         796 :         if (!SurfError) {
    2444       46840 :             for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
    2445       46044 :                 auto &surf = state.dataSurface->Surface(SurfNum);
    2446       46044 :                 if (surf.HasShadeControl) {
    2447         151 :                     WinShadingControlPtr = surf.activeWindowShadingControl; // use first item since others should be identical
    2448         151 :                     if (state.dataSurface->WindowShadingControl(WinShadingControlPtr).slatAngleControl != SlatAngleControl::Fixed) {
    2449           3 :                         state.dataSurface->SurfWinMovableSlats(SurfNum) = true;
    2450           3 :                         state.dataSurface->AnyMovableSlat = true;
    2451           3 :                         state.dataHeatBalSurf->SurfMovSlatsIndexList.push_back(SurfNum);
    2452             :                     }
    2453             : 
    2454         151 :                     ConstrNumSh = surf.activeShadedConstruction;
    2455         151 :                     if (ConstrNumSh <= 0) continue;
    2456             : 
    2457         151 :                     WinShadingType ShadingType = state.dataSurface->WindowShadingControl(WinShadingControlPtr).ShadingType;
    2458             : 
    2459             :                     // only for blinds
    2460         151 :                     if (ANY_BLIND(ShadingType)) {
    2461             : 
    2462             :                         // TH 1/7/2010. CR 7930
    2463             :                         // The old code did not consider between-glass blind. Also there should not be two blinds - both interior and exterior
    2464             :                         // Use the new generic code (assuming only one blind) as follows
    2465          91 :                         for (iTmp1 = 1; iTmp1 <= state.dataConstruction->Construct(ConstrNumSh).TotLayers; ++iTmp1) {
    2466          91 :                             iTmp2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(iTmp1);
    2467          91 :                             auto *mat = state.dataMaterial->Material(iTmp2);
    2468             : 
    2469          91 :                             if (mat->group != Material::Group::WindowBlind) continue;
    2470             : 
    2471          42 :                             auto *matBlind = dynamic_cast<Material::MaterialChild *>(mat);
    2472          42 :                             assert(matBlind != nullptr);
    2473             : 
    2474          42 :                             BlNum = matBlind->BlindDataPtr;
    2475          42 :                             state.dataSurface->SurfWinBlindNumber(SurfNum) = BlNum;
    2476             :                             // TH 2/18/2010. CR 8010
    2477             :                             // if it is a blind with movable slats, create one new blind and set it to VariableSlat if not done so yet.
    2478             :                             //  the new blind is created only once, it can be shared by multiple windows though.
    2479          45 :                             if (state.dataSurface->SurfWinMovableSlats(SurfNum) &&
    2480           3 :                                 state.dataMaterial->Blind(BlNum).SlatAngleType != DataWindowEquivalentLayer::AngleType::Variable) {
    2481           3 :                                 errFlag = false;
    2482           3 :                                 AddVariableSlatBlind(state, BlNum, BlNumNew, errFlag);
    2483             :                                 // point to the new blind
    2484           3 :                                 matBlind->BlindDataPtr = BlNumNew;
    2485             :                                 // window surface points to new blind
    2486           3 :                                 state.dataSurface->SurfWinBlindNumber(SurfNum) = BlNumNew;
    2487             :                             }
    2488          42 :                             break;
    2489             :                         }
    2490             : 
    2491          42 :                         if (errFlag) {
    2492           0 :                             ErrorsFound = true;
    2493           0 :                             ShowContinueError(state,
    2494           0 :                                               format("WindowShadingControl {} has errors, program will terminate.",
    2495           0 :                                                      state.dataSurface->WindowShadingControl(WinShadingControlPtr).Name));
    2496             :                         }
    2497             :                     }
    2498             :                 } // End of surface loop
    2499             : 
    2500             :                 // final associate fenestration surfaces referenced in WindowShadingControl
    2501       46044 :                 FinalAssociateWindowShadingControlFenestration(state, ErrorsFound);
    2502       46044 :                 CheckWindowShadingControlSimilarForWindow(state, ErrorsFound);
    2503             :             }
    2504             : 
    2505             :             // Check for zones with not enough surfaces
    2506        5852 :             for (auto &thisZone : state.dataHeatBal->Zone) {
    2507        5056 :                 int OpaqueHTSurfs = 0;        // Number of floors, walls and roofs in a zone
    2508        5056 :                 int OpaqueHTSurfsWithWin = 0; // Number of floors, walls and roofs with windows in a zone
    2509        5056 :                 int InternalMassSurfs = 0;    // Number of internal mass surfaces in a zone
    2510        5056 :                 int priorBaseSurfNum = 0;
    2511             : 
    2512       10124 :                 for (int spaceNum : thisZone.spaceIndexes) {
    2513        5068 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2514        5068 :                     if (thisSpace.HTSurfaceFirst == 0) continue; // Zone with no surfaces
    2515       49458 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    2516       44390 :                         auto &thisSurf = state.dataSurface->Surface(SurfNum);
    2517       44390 :                         if (thisSurf.Class == SurfaceClass::Floor || thisSurf.Class == SurfaceClass::Wall || thisSurf.Class == SurfaceClass::Roof)
    2518       35294 :                             ++OpaqueHTSurfs;
    2519       44390 :                         if (thisSurf.Class == SurfaceClass::IntMass) ++InternalMassSurfs;
    2520       44390 :                         if (thisSurf.Class == SurfaceClass::Window) {
    2521             :                             // Count base surface only once for multiple windows on a wall
    2522        6217 :                             int thisBaseSurfNum = thisSurf.BaseSurf;
    2523        6217 :                             if (thisBaseSurfNum != priorBaseSurfNum) {
    2524        4133 :                                 ++OpaqueHTSurfsWithWin;
    2525        4133 :                                 priorBaseSurfNum = thisBaseSurfNum;
    2526             :                             }
    2527             :                         }
    2528             :                     }
    2529        5056 :                 }
    2530        5056 :                 if (OpaqueHTSurfsWithWin == 1 && OpaqueHTSurfs == 1 && InternalMassSurfs == 0) {
    2531           0 :                     SurfError = true;
    2532           0 :                     ShowSevereError(state,
    2533           0 :                                     format("{}Zone {} has only one floor, wall or roof, and this surface has a window.", RoutineName, thisZone.Name));
    2534           0 :                     ShowContinueError(state, "Add more floors, walls or roofs, or an internal mass surface.");
    2535             :                 }
    2536         796 :             }
    2537             : 
    2538             :             // set up vertex of centroid for each surface.
    2539         796 :             CalcSurfaceCentroid(state);
    2540             : 
    2541         796 :             SetupShadeSurfacesForSolarCalcs(state); // if shading surfaces are solar collectors or PV, then we need full solar calc.
    2542             : 
    2543         796 :             GetMovableInsulationData(state, ErrorsFound);
    2544             : 
    2545         796 :             if (state.dataSurface->CalcSolRefl) GetShadingSurfReflectanceData(state, ErrorsFound);
    2546             : 
    2547         796 :             LayNumOutside = 0;
    2548       46840 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2549       46044 :                 auto &surf = state.dataSurface->Surface(SurfNum);
    2550             :                 // Check for EcoRoof and only 1 allowed to be used.
    2551       46044 :                 if (surf.Construction > 0)
    2552       44408 :                     state.dataSurface->SurfExtEcoRoof(SurfNum) = state.dataConstruction->Construct(surf.Construction).TypeIsEcoRoof;
    2553       46044 :                 if (!state.dataSurface->SurfExtEcoRoof(SurfNum)) continue;
    2554          20 :                 if (LayNumOutside == 0) {
    2555           4 :                     LayNumOutside = state.dataConstruction->Construct(surf.Construction).LayerPoint(1);
    2556           4 :                     continue;
    2557             :                 }
    2558          16 :                 if (LayNumOutside != state.dataConstruction->Construct(surf.Construction).LayerPoint(1)) {
    2559           0 :                     ShowSevereError(state, format("{}Only one EcoRoof Material is currently allowed for all constructions.", RoutineName));
    2560           0 :                     ShowContinueError(state, format("... first material={}", state.dataMaterial->Material(LayNumOutside)->Name));
    2561           0 :                     ShowContinueError(state,
    2562           0 :                                       format("... conflicting Construction={} uses material={}",
    2563           0 :                                              state.dataConstruction->Construct(surf.Construction).Name,
    2564           0 :                                              state.dataMaterial->Material(state.dataConstruction->Construct(surf.Construction).LayerPoint(1))->Name));
    2565           0 :                     ErrorsFound = true;
    2566             :                 }
    2567             :             }
    2568             : 
    2569             :             // Reserve space to avoid excess allocations
    2570         796 :             state.dataSurface->AllHTSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2571         796 :             state.dataSurface->AllExtSolarSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2572         796 :             state.dataSurface->AllShadowPossObstrSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2573         796 :             state.dataSurface->AllIZSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2574         796 :             state.dataSurface->AllHTNonWindowSurfaceList.reserve(state.dataSurface->TotSurfaces - state.dataSurface->TotWindows);
    2575         796 :             state.dataSurface->AllHTWindowSurfaceList.reserve(state.dataSurface->TotWindows);
    2576         796 :             state.dataSurface->AllExtSolWindowSurfaceList.reserve(state.dataSurface->TotWindows);
    2577         796 :             state.dataSurface->AllExtSolWinWithFrameSurfaceList.reserve(state.dataSurface->TotWindows);
    2578         796 :             state.dataSurface->AllHTKivaSurfaceList.reserve(state.dataSurface->TotSurfaces);
    2579             : 
    2580             :             // Set flag that determines whether a surface can be an exterior obstruction
    2581             :             // Also set associated surfaces for Kiva foundations and build heat transfer surface lists
    2582       46840 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2583       46044 :                 auto &surf = state.dataSurface->Surface(SurfNum);
    2584       46044 :                 surf.IsShadowPossibleObstruction = false;
    2585       46044 :                 if (surf.ExtSolar) {
    2586             :                     // This may include some attached shading surfaces
    2587       19332 :                     state.dataSurface->AllExtSolarSurfaceList.push_back(SurfNum);
    2588             :                 }
    2589       46044 :                 if (surf.HeatTransSurf) {
    2590             :                     // Outside light shelves get tagged later as HeatTransSurf=true but they haven't been processed yet
    2591       44390 :                     state.dataSurface->AllHTSurfaceList.push_back(SurfNum);
    2592       44390 :                     int const zoneNum(surf.Zone);
    2593       44390 :                     auto &surfZone(state.dataHeatBal->Zone(zoneNum));
    2594       44390 :                     surfZone.ZoneHTSurfaceList.push_back(SurfNum);
    2595             :                     // Sort window vs non-window surfaces
    2596       44390 :                     if (surf.Class == DataSurfaces::SurfaceClass::Window) {
    2597        6217 :                         state.dataSurface->AllHTWindowSurfaceList.push_back(SurfNum);
    2598        6217 :                         surfZone.ZoneHTWindowSurfaceList.push_back(SurfNum);
    2599        6217 :                         if (surf.ExtSolar) {
    2600        6201 :                             state.dataSurface->AllExtSolWindowSurfaceList.push_back(SurfNum);
    2601        6201 :                             if (surf.FrameDivider > 0) {
    2602         381 :                                 state.dataSurface->AllExtSolWinWithFrameSurfaceList.push_back(SurfNum);
    2603             :                             }
    2604             :                         }
    2605             :                     } else {
    2606       38173 :                         state.dataSurface->AllHTNonWindowSurfaceList.push_back(SurfNum);
    2607       38173 :                         surfZone.ZoneHTNonWindowSurfaceList.push_back(SurfNum);
    2608             :                     }
    2609       44390 :                     int const surfExtBoundCond(surf.ExtBoundCond);
    2610             :                     // Build zone and interzone surface lists
    2611       44390 :                     if ((surfExtBoundCond > 0) && (surfExtBoundCond != SurfNum)) {
    2612       17806 :                         state.dataSurface->AllIZSurfaceList.push_back(SurfNum);
    2613       17806 :                         surfZone.ZoneIZSurfaceList.push_back(SurfNum);
    2614       17806 :                         auto &adjZone(state.dataHeatBal->Zone(state.dataSurface->Surface(surfExtBoundCond).Zone));
    2615       17806 :                         adjZone.ZoneHTSurfaceList.push_back(SurfNum);
    2616       17806 :                         adjZone.ZoneIZSurfaceList.push_back(SurfNum);
    2617             :                         // Sort window vs non-window surfaces
    2618       17806 :                         if (surf.Class == DataSurfaces::SurfaceClass::Window) {
    2619          14 :                             adjZone.ZoneHTWindowSurfaceList.push_back(SurfNum);
    2620             :                         } else {
    2621       17792 :                             adjZone.ZoneHTNonWindowSurfaceList.push_back(SurfNum);
    2622             :                         }
    2623             :                     }
    2624             :                 }
    2625             : 
    2626             :                 // Exclude non-exterior heat transfer surfaces (but not OtherSideCondModeledExt = -4 CR7640)
    2627       46044 :                 if (surf.HeatTransSurf && surf.ExtBoundCond > 0) continue;
    2628       21964 :                 if (surf.HeatTransSurf && surf.ExtBoundCond == Ground) continue;
    2629       19763 :                 if (surf.HeatTransSurf && surf.ExtBoundCond == KivaFoundation) {
    2630          38 :                     state.dataSurface->AllHTKivaSurfaceList.push_back(SurfNum);
    2631          38 :                     if (!ErrorsFound) state.dataSurfaceGeometry->kivaManager.foundationInputs[surf.OSCPtr].surfaces.push_back(SurfNum);
    2632          38 :                     continue;
    2633             :                 }
    2634       19725 :                 if (surf.HeatTransSurf && surf.ExtBoundCond == OtherSideCoefNoCalcExt) continue;
    2635       19693 :                 if (surf.HeatTransSurf && surf.ExtBoundCond == OtherSideCoefCalcExt) continue;
    2636             :                 // Exclude windows and doors, i.e., consider only their base surfaces as possible obstructions
    2637       19692 :                 if (surf.Class == SurfaceClass::Window || surf.Class == SurfaceClass::Door) continue;
    2638             :                 // Exclude duplicate shading surfaces
    2639       13091 :                 if (surf.MirroredSurf) continue;
    2640             :                 // Exclude air boundary surfaces
    2641       12273 :                 if (surf.IsAirBoundarySurf) continue;
    2642             : 
    2643       12255 :                 surf.IsShadowPossibleObstruction = true;
    2644       12255 :                 state.dataSurface->AllShadowPossObstrSurfaceList.push_back(SurfNum);
    2645             :             }
    2646             : 
    2647             :             // Check for IRT surfaces in invalid places.
    2648         796 :             iTmp1 = 0;
    2649         796 :             if (std::any_of(state.dataConstruction->Construct.begin(),
    2650         796 :                             state.dataConstruction->Construct.end(),
    2651        6022 :                             [](Construction::ConstructionProps const &e) { return e.TypeIsIRT; })) {
    2652          76 :                 for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2653          74 :                     auto &surf = state.dataSurface->Surface(SurfNum);
    2654          74 :                     if (!surf.HeatTransSurf) continue;                                   // ignore shading surfaces
    2655          74 :                     if (surf.ExtBoundCond > 0 && surf.ExtBoundCond != SurfNum) continue; // interzone, not adiabatic surface
    2656          46 :                     if (!state.dataConstruction->Construct(surf.Construction).TypeIsIRT) {
    2657          46 :                         continue;
    2658             :                     }
    2659           0 :                     if (!state.dataGlobal->DisplayExtraWarnings) {
    2660           0 :                         ++iTmp1;
    2661             :                     } else {
    2662           0 :                         ShowWarningError(state,
    2663           0 :                                          format("{}Surface=\"{}\" uses InfraredTransparent construction in a non-interzone surface. (illegal use)",
    2664             :                                                 RoutineName,
    2665           0 :                                                 surf.Name));
    2666             :                     }
    2667             :                 }
    2668           2 :                 if (iTmp1 > 0) {
    2669           0 :                     ShowWarningError(
    2670             :                         state,
    2671           0 :                         format("{}Surfaces use InfraredTransparent constructions {} in non-interzone surfaces. (illegal use)", RoutineName, iTmp1));
    2672           0 :                     ShowContinueError(state, "For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;");
    2673             :                 }
    2674             :             }
    2675             : 
    2676             :             // Populate SurfaceFilter lists
    2677        8756 :             for (int iSurfaceFilter = 1; iSurfaceFilter < static_cast<int>(SurfaceFilter::Num); ++iSurfaceFilter)
    2678        7960 :                 state.dataSurface->SurfaceFilterLists[iSurfaceFilter].reserve(state.dataSurface->TotSurfaces);
    2679             : 
    2680       46840 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2681       46044 :                 auto const &surf = state.dataSurface->Surface(SurfNum);
    2682       46044 :                 if (!surf.HeatTransSurf) continue;
    2683       44390 :                 if (surf.ExtBoundCond > 0) {
    2684       24080 :                     state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorSurfaces)].push_back(SurfNum);
    2685       24080 :                     if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) {
    2686          14 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorWindows)].push_back(SurfNum);
    2687       24066 :                     } else if (surf.Class == SurfaceClass::Wall) {
    2688       13478 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorWalls)].push_back(SurfNum);
    2689       10588 :                     } else if (surf.Class == SurfaceClass::Floor) {
    2690        4548 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorFloors)].push_back(SurfNum);
    2691        6040 :                     } else if (surf.Class == SurfaceClass::Roof) {
    2692        3578 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorRoofs)].push_back(SurfNum);
    2693        3578 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorCeilings)].push_back(SurfNum);
    2694             :                     }
    2695             :                 } else {
    2696       20310 :                     state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllExteriorSurfaces)].push_back(SurfNum);
    2697       20310 :                     if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) {
    2698        6205 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllExteriorWindows)].push_back(SurfNum);
    2699       14105 :                     } else if (surf.Class == SurfaceClass::Wall) {
    2700        9125 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllExteriorWalls)].push_back(SurfNum);
    2701        4980 :                     } else if (surf.Class == SurfaceClass::Floor) {
    2702        2342 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllExteriorFloors)].push_back(SurfNum);
    2703        2638 :                     } else if (surf.Class == SurfaceClass::Roof) {
    2704        2223 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllExteriorRoofs)].push_back(SurfNum);
    2705        2223 :                         state.dataSurface->SurfaceFilterLists[static_cast<int>(SurfaceFilter::AllInteriorCeilings)].push_back(SurfNum);
    2706             :                     }
    2707             :                 }
    2708             :             }
    2709             : 
    2710             :             // Note, could do same for Window Area and detecting if Interzone Surface in Zone
    2711             : 
    2712         796 :             if (state.dataSurfaceGeometry->Warning1Count > 0) {
    2713          10 :                 ShowWarningMessage(state,
    2714          10 :                                    format("{}Window dimensions differ from Window 5/6 data file dimensions, {} times.",
    2715             :                                           RoutineName,
    2716           5 :                                           state.dataSurfaceGeometry->Warning1Count));
    2717           5 :                 ShowContinueError(state, "This will affect the frame heat transfer calculation if the frame in the Data File entry");
    2718           5 :                 ShowContinueError(state, "is not uniform, i.e., has sections with different geometry and/or thermal properties.");
    2719           5 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2720             :             }
    2721         796 :             if (state.dataSurfaceGeometry->Warning2Count > 0) {
    2722           0 :                 ShowWarningMessage(state,
    2723           0 :                                    format("{}Exterior Windows have been replaced with Window 5/6 two glazing systems, {} times.",
    2724             :                                           RoutineName,
    2725           0 :                                           state.dataSurfaceGeometry->Warning2Count));
    2726           0 :                 ShowContinueError(state, "Note that originally entered dimensions are overridden.");
    2727           0 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2728             :             }
    2729         796 :             if (state.dataSurfaceGeometry->Warning3Count > 0) {
    2730           0 :                 ShowWarningMessage(state,
    2731           0 :                                    format("{}Interior Windows have been replaced with Window 5/6 two glazing systems, {} times.",
    2732             :                                           RoutineName,
    2733           0 :                                           state.dataSurfaceGeometry->Warning3Count));
    2734           0 :                 ShowContinueError(state, "Note that originally entered dimensions are overridden.");
    2735           0 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2736             :             }
    2737             : 
    2738         796 :             if (state.dataErrTracking->TotalMultipliedWindows > 0) {
    2739           2 :                 ShowWarningMessage(state,
    2740           2 :                                    format("{}There are {} window/glass door(s) that may cause inaccurate shadowing due to Solar Distribution.",
    2741             :                                           RoutineName,
    2742           1 :                                           state.dataErrTracking->TotalMultipliedWindows));
    2743           1 :                 ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
    2744           1 :                 state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalMultipliedWindows;
    2745             :             }
    2746         796 :             if (state.dataErrTracking->TotalCoincidentVertices > 0) {
    2747           0 :                 ShowWarningMessage(state,
    2748           0 :                                    format("{}There are {} coincident/collinear vertices; These have been deleted unless the deletion would bring the "
    2749             :                                           "number of surface sides < 3.",
    2750             :                                           RoutineName,
    2751           0 :                                           state.dataErrTracking->TotalCoincidentVertices));
    2752           0 :                 ShowContinueError(state, "For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;");
    2753           0 :                 state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalCoincidentVertices;
    2754             :             }
    2755         796 :             if (state.dataErrTracking->TotalDegenerateSurfaces > 0) {
    2756           0 :                 ShowSevereMessage(state,
    2757           0 :                                   format("{}There are {} degenerate surfaces; Degenerate surfaces are those with number of sides < 3.",
    2758             :                                          RoutineName,
    2759           0 :                                          state.dataErrTracking->TotalDegenerateSurfaces));
    2760           0 :                 ShowContinueError(state, "These surfaces should be deleted.");
    2761           0 :                 ShowContinueError(state, "For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;");
    2762           0 :                 state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalDegenerateSurfaces;
    2763             :             }
    2764             : 
    2765         796 :             GetHTSurfExtVentedCavityData(state, ErrorsFound);
    2766             : 
    2767         796 :             state.dataSurfaceGeometry->exposedFoundationPerimeter.getData(state, ErrorsFound);
    2768             : 
    2769         796 :             GetSurfaceHeatTransferAlgorithmOverrides(state, ErrorsFound);
    2770             : 
    2771             :             // Set up enclosures, process Air Boundaries if any
    2772         796 :             SetupEnclosuresAndAirBoundaries(state, state.dataViewFactor->EnclRadInfo, SurfaceGeometry::enclosureType::RadiantEnclosures, ErrorsFound);
    2773             : 
    2774         796 :             GetSurfaceGroundSurfsData(state, ErrorsFound);
    2775             : 
    2776         796 :             GetSurfaceSrdSurfsData(state, ErrorsFound);
    2777             : 
    2778         796 :             GetSurfaceLocalEnvData(state, ErrorsFound);
    2779             : 
    2780         796 :             if (SurfError || ErrorsFound) {
    2781           0 :                 ErrorsFound = true;
    2782           0 :                 ShowFatalError(state, format("{}Errors discovered, program terminates.", RoutineName));
    2783             :             }
    2784             : 
    2785         796 :             int TotShadSurf = TotDetachedFixed + TotDetachedBldg + TotRectDetachedFixed + TotRectDetachedBldg + TotShdSubs + TotOverhangs +
    2786         796 :                               TotOverhangsProjection + TotFins + TotFinsProjection;
    2787         796 :             int NumDElightCmplxFen = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Daylighting:DElight:ComplexFenestration");
    2788         796 :             if (TotShadSurf > 0 && (NumDElightCmplxFen > 0 || Dayltg::doesDayLightingUseDElight(state))) {
    2789           0 :                 ShowWarningError(state,
    2790           0 :                                  format("{}When using DElight daylighting the presence of exterior shading surfaces is ignored.", RoutineName));
    2791             :             }
    2792             : 
    2793       46840 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
    2794       46044 :                 auto &surf = state.dataSurface->Surface(SurfNum);
    2795             :                 // Initialize run time surface arrays
    2796       46044 :                 state.dataSurface->SurfActiveConstruction(SurfNum) = surf.Construction;
    2797       46044 :                 surf.RepresentativeCalcSurfNum = SurfNum;
    2798             :             }
    2799             : 
    2800             :             // Representative surface calculations: Assign representative heat transfer surfaces
    2801         797 :             if (state.dataSurface->UseRepresentativeSurfaceCalculations &&
    2802         797 :                 state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneProperty:UserViewFactors:BySurfaceName") == 0) {
    2803          47 :                 for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2804          92 :                     for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2805          46 :                         auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2806         625 :                         for (int surfNum = thisSpace.HTSurfaceFirst; surfNum <= thisSpace.HTSurfaceLast; surfNum++) {
    2807         579 :                             auto &surface(state.dataSurface->Surface(surfNum));
    2808             :                             // Conditions where surface always needs to be unique
    2809             :                             bool forceUniqueSurface =
    2810        1158 :                                 surface.HasShadeControl ||
    2811         579 :                                 state.dataSurface->SurfWinAirflowSource(surfNum) != DataSurfaces::WindowAirFlowSource::Invalid ||
    2812         579 :                                 state.dataConstruction->Construct(surface.Construction).SourceSinkPresent ||
    2813        1737 :                                 surface.Class == SurfaceClass::TDD_Dome ||
    2814         579 :                                 (surface.Class == SurfaceClass::Window &&
    2815         178 :                                  (surface.OriginalClass == SurfaceClass::TDD_Diffuser ||
    2816         178 :                                   state.dataSurface->SurfWinWindowModelType(surfNum) != WindowModel::Detailed ||
    2817         178 :                                   state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() ||
    2818         178 :                                   state.dataConstruction->Construct(surface.Construction).TCFlag == 1));
    2819         579 :                             if (!forceUniqueSurface) {
    2820         579 :                                 state.dataSurface->Surface(surfNum).set_representative_surface(state, surfNum);
    2821             :                             }
    2822             :                         }
    2823          46 :                     }
    2824             :                 }
    2825             :             }
    2826             :             // Initialize surface with movable insulation index list
    2827       46840 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
    2828       46044 :                 if (state.dataSurface->SurfMaterialMovInsulExt(SurfNum) > 0 || state.dataSurface->SurfMaterialMovInsulInt(SurfNum) > 0) {
    2829           5 :                     state.dataHeatBalSurf->SurfMovInsulIndexList.push_back(SurfNum);
    2830             :                 }
    2831             :             }
    2832             :         }
    2833         796 :         if (SurfError || ErrorsFound) {
    2834           0 :             ErrorsFound = true;
    2835           0 :             ShowFatalError(state, format("{}Errors discovered, program terminates.", RoutineName));
    2836             :         }
    2837         796 :     }
    2838             : 
    2839         796 :     void CreateMissingSpaces(EnergyPlusData &state, Array1D<SurfaceGeometry::SurfaceData> &Surfaces)
    2840             :     {
    2841             :         // Scan surfaces to see if Space was assigned in input
    2842         796 :         EPVector<bool> anySurfacesWithSpace;    // True if any surfaces in a zone do not have a space assigned in input
    2843         796 :         EPVector<bool> anySurfacesWithoutSpace; // True if any surfaces in a zone have a space assigned in input
    2844         796 :         anySurfacesWithSpace.resize(state.dataGlobal->NumOfZones, false);
    2845         796 :         anySurfacesWithoutSpace.resize(state.dataGlobal->NumOfZones, false);
    2846             : 
    2847       46840 :         for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
    2848       46044 :             auto &thisSurf = Surfaces(surfNum);
    2849       46044 :             if (!thisSurf.HeatTransSurf) continue;                               // ignore shading surfaces
    2850       44408 :             if (thisSurf.Class == DataSurfaces::SurfaceClass::IntMass) continue; // skip internal mass surfaces for this check
    2851       42010 :             if (thisSurf.BaseSurf != surfNum) {
    2852             :                 // Set space for subsurfaces
    2853        6698 :                 thisSurf.spaceNum = Surfaces(thisSurf.BaseSurf).spaceNum;
    2854             :             }
    2855       42010 :             if (thisSurf.spaceNum > 0) {
    2856          69 :                 anySurfacesWithSpace(thisSurf.Zone) = true;
    2857             :             } else {
    2858       41941 :                 anySurfacesWithoutSpace(thisSurf.Zone) = true;
    2859             :             }
    2860             :         }
    2861             : 
    2862             :         // Create any missing Spaces
    2863        5852 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2864        5056 :             auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    2865        5056 :             if (anySurfacesWithoutSpace(zoneNum)) {
    2866             :                 // If any surfaces in the zone are not assigned to a space, may need to create a new space
    2867             :                 // Every zone has at least one space, created in HeatBalanceManager::GetSpaceData
    2868             :                 // If no surfaces have a space assigned, then the default space will be used, otherwise, create a new space
    2869        5052 :                 if (anySurfacesWithSpace(zoneNum)) {
    2870             :                     // Add new space
    2871           3 :                     ++state.dataGlobal->numSpaces;
    2872           3 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).zoneNum = zoneNum;
    2873             :                     // Add to zone's list of spaces
    2874           3 :                     thisZone.spaceIndexes.emplace_back(state.dataGlobal->numSpaces);
    2875           3 :                     ++state.dataHeatBal->Zone(zoneNum).numSpaces;
    2876           3 :                     assert(state.dataHeatBal->Zone(zoneNum).numSpaces == int(state.dataHeatBal->Zone(zoneNum).spaceIndexes.size()));
    2877             :                     // If some surfaces in the zone are assigned to a space, the new space is the remainder of the zone
    2878           3 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).Name =
    2879           6 :                         thisZone.Name + "-REMAINDER"; // Make UPPERcase so it can be referenced in input
    2880           3 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).isRemainderSpace = true;
    2881           3 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceType = "GENERAL";
    2882           3 :                     state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceTypeNum = HeatBalanceManager::GetGeneralSpaceTypeNum(state);
    2883             :                 }
    2884             :             }
    2885             :         }
    2886             : 
    2887             :         // Assign Spaces to surfaces without one
    2888       46840 :         for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
    2889       46044 :             auto &thisSurf = Surfaces(surfNum);
    2890       46044 :             if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
    2891       44408 :             if (thisSurf.spaceNum == 0) {
    2892       44329 :                 int const numSpaces = state.dataHeatBal->Zone(thisSurf.Zone).numSpaces;
    2893       44329 :                 int const lastSpaceForZone = state.dataHeatBal->Zone(thisSurf.Zone).spaceIndexes(numSpaces);
    2894       44329 :                 thisSurf.spaceNum = lastSpaceForZone;
    2895             :             }
    2896             :         }
    2897         796 :     }
    2898             : 
    2899         796 :     void createSpaceSurfaceLists(EnergyPlusData &state)
    2900             :     {
    2901             :         static constexpr std::string_view RoutineName("createSpaceSurfaceLists: ");
    2902             :         // Build Space surface lists now that all of the surface sorting is complete
    2903       46840 :         for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
    2904       46044 :             auto &thisSurf = state.dataSurface->Surface(surfNum);
    2905       46044 :             if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
    2906             :             // Add to Space's list of surfaces
    2907       44408 :             state.dataHeatBal->space(thisSurf.spaceNum).surfaces.emplace_back(surfNum);
    2908             :         }
    2909        5864 :         for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
    2910        5068 :             if (int(state.dataHeatBal->space(spaceNum).surfaces.size()) == 0) {
    2911           0 :                 ShowWarningError(state, format("{}Space={} has no surfaces.", RoutineName, state.dataHeatBal->space(spaceNum).Name));
    2912             :             }
    2913             :         }
    2914         796 :     }
    2915             : 
    2916         796 :     void setSurfaceFirstLast(EnergyPlusData &state)
    2917             :     {
    2918             :         // Set Zone and Space Surface First/Last Pointers
    2919             :         // Space surface lists have been built earlier in createSpaceSurfaceLists
    2920        5852 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2921       10124 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    2922        5068 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2923       49476 :                 for (int SurfNum : thisSpace.surfaces) {
    2924       44408 :                     auto &surf = state.dataSurface->Surface(SurfNum);
    2925       44408 :                     if (thisSpace.AllSurfaceFirst == 0) {
    2926        5068 :                         thisSpace.AllSurfaceFirst = SurfNum;
    2927             :                     }
    2928       44408 :                     thisSpace.AllSurfaceLast = SurfNum;
    2929             : 
    2930       44408 :                     if (surf.IsAirBoundarySurf) {
    2931          18 :                         surf.HeatTransSurf = false;
    2932          18 :                         continue;
    2933             :                     }
    2934             :                     // Non window surfaces are grouped next within each space
    2935       44390 :                     if (thisSpace.HTSurfaceFirst == 0) {
    2936        5068 :                         thisSpace.HTSurfaceFirst = SurfNum;
    2937        5068 :                         thisSpace.OpaqOrIntMassSurfaceFirst = SurfNum;
    2938        5068 :                         thisSpace.OpaqOrWinSurfaceFirst = SurfNum;
    2939             :                     }
    2940       44390 :                     thisSpace.HTSurfaceLast = SurfNum;
    2941             : 
    2942             :                     // Window surfaces are grouped next within each space
    2943       44390 :                     if ((surf.Class == DataSurfaces::SurfaceClass::Window) || (surf.Class == DataSurfaces::SurfaceClass::GlassDoor) ||
    2944       38175 :                         (surf.Class == DataSurfaces::SurfaceClass::TDD_Diffuser)) {
    2945        6217 :                         if (thisSpace.WindowSurfaceFirst == 0) {
    2946        3153 :                             thisSpace.WindowSurfaceFirst = SurfNum;
    2947             :                         }
    2948        6217 :                         thisSpace.WindowSurfaceLast = SurfNum;
    2949       38173 :                     } else if (surf.Class != DataSurfaces::SurfaceClass::TDD_Dome) {
    2950       38171 :                         thisSpace.OpaqOrIntMassSurfaceLast = SurfNum;
    2951             :                     }
    2952             : 
    2953             :                     // TDDDome surfaces are grouped last within each space
    2954       44390 :                     if (surf.Class == DataSurfaces::SurfaceClass::TDD_Dome) {
    2955           2 :                         if (thisSpace.TDDDomeFirst == 0) {
    2956           1 :                             thisSpace.TDDDomeFirst = SurfNum;
    2957             :                         }
    2958           2 :                         thisSpace.TDDDomeLast = SurfNum;
    2959             :                     } else {
    2960       44388 :                         thisSpace.OpaqOrWinSurfaceLast = SurfNum;
    2961             :                     }
    2962        5068 :                 }
    2963        5068 :                 state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast = thisSpace.AllSurfaceLast;
    2964        5056 :             }
    2965        5056 :             int firstSpaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
    2966        5056 :             state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst = state.dataHeatBal->space(firstSpaceNum).AllSurfaceFirst;
    2967             :         }
    2968         796 :     }
    2969             : 
    2970        6698 :     void checkSubSurfAzTiltNorm(EnergyPlusData &state,
    2971             :                                 SurfaceData &baseSurface, // Base surface data (in)
    2972             :                                 SurfaceData &subSurface,  // Subsurface data (in)
    2973             :                                 bool &surfaceError        // True if surface azimuths or tilts differ by more than error tolerance
    2974             :     )
    2975             :     {
    2976        6698 :         bool sameSurfNormal(false); // True if surface has the same surface normal within tolerance
    2977        6698 :         bool baseSurfHoriz(false);  // True if base surface is near horizontal
    2978        6698 :         Real64 constexpr warningTolerance(30.0);
    2979        6698 :         Real64 constexpr errorTolerance(90.0);
    2980             : 
    2981        6698 :         surfaceError = false;
    2982             : 
    2983             :         // Check if base surface and subsurface have the same normal
    2984        6698 :         Vectors::CompareTwoVectors(baseSurface.NewellSurfaceNormalVector, subSurface.NewellSurfaceNormalVector, sameSurfNormal, 0.001);
    2985        6698 :         if (sameSurfNormal) { // copy lcs vectors
    2986             :                               // Prior logic tested for azimuth difference < 30 and then skipped this - this caused large diffs in
    2987             :                               // CmplxGlz_MeasuredDeflectionAndShading Restoring that check here but will require further investigation (MJW Dec 2015)
    2988             :                               // if (std::abs(baseSurface.Azimuth - subSurface.Azimuth) > warningTolerance) {
    2989        6697 :             subSurface.lcsx = baseSurface.lcsx;
    2990        6697 :             subSurface.lcsy = baseSurface.lcsy;
    2991        6697 :             subSurface.lcsz = baseSurface.lcsz;
    2992             :             // }
    2993             :         } else {
    2994             :             // // Not sure what this does, but keeping for now (MJW Dec 2015)
    2995             :             // if (std::abs(subSurface.Azimuth - 360.0) < 0.01) {
    2996             :             //     subSurface.Azimuth = 360.0 - subSurface.Azimuth;
    2997             :             // }
    2998             :             // if (std::abs(baseSurface.Azimuth - 360.0) < 0.01) {
    2999             :             //     baseSurface.Azimuth = 360.0 - baseSurface.Azimuth;
    3000             :             // }
    3001             : 
    3002             :             // Is base surface horizontal? If so, ignore azimuth differences
    3003           1 :             if (std::abs(baseSurface.Tilt) <= 1.0e-5 || std::abs(baseSurface.Tilt - 180.0) <= 1.0e-5) baseSurfHoriz = true;
    3004             : 
    3005           2 :             if (((General::rotAzmDiffDeg(baseSurface.Azimuth, subSurface.Azimuth) > errorTolerance) && !baseSurfHoriz) ||
    3006           1 :                 (std::abs(baseSurface.Tilt - subSurface.Tilt) > errorTolerance)) {
    3007           0 :                 surfaceError = true;
    3008           0 :                 ShowSevereError(
    3009             :                     state,
    3010           0 :                     format("checkSubSurfAzTiltNorm: Outward facing angle of subsurface differs more than {:.1R} degrees from base surface.",
    3011             :                            errorTolerance));
    3012           0 :                 ShowContinueError(state,
    3013           0 :                                   format("Subsurface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", subSurface.Name, subSurface.Tilt, subSurface.Azimuth));
    3014           0 :                 ShowContinueError(
    3015           0 :                     state, format("Base surface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", baseSurface.Name, baseSurface.Tilt, baseSurface.Azimuth));
    3016           2 :             } else if (((General::rotAzmDiffDeg(baseSurface.Azimuth, subSurface.Azimuth) > warningTolerance) && !baseSurfHoriz) ||
    3017           1 :                        (std::abs(baseSurface.Tilt - subSurface.Tilt) > warningTolerance)) {
    3018           0 :                 ++state.dataSurfaceGeometry->checkSubSurfAzTiltNormErrCount;
    3019           0 :                 if (state.dataSurfaceGeometry->checkSubSurfAzTiltNormErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    3020           0 :                     ShowWarningError(state,
    3021           0 :                                      format("checkSubSurfAzTiltNorm: Some Outward Facing angles of subsurfaces differ more than {:.1R} "
    3022             :                                             "degrees from base surface.",
    3023             :                                             warningTolerance));
    3024           0 :                     ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
    3025             :                 }
    3026           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
    3027           0 :                     ShowWarningError(
    3028             :                         state,
    3029           0 :                         format("checkSubSurfAzTiltNorm: Outward facing angle of subsurface differs more than {:.1R} degrees from base surface.",
    3030             :                                warningTolerance));
    3031           0 :                     ShowContinueError(
    3032           0 :                         state, format("Subsurface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", subSurface.Name, subSurface.Tilt, subSurface.Azimuth));
    3033           0 :                     ShowContinueError(
    3034             :                         state,
    3035           0 :                         format("Base surface=\"{}\" Tilt = {:.1R}  Azimuth = {:.1R}", baseSurface.Name, baseSurface.Tilt, baseSurface.Azimuth));
    3036             :                 }
    3037             :             }
    3038             :         }
    3039        6698 :     }
    3040             : 
    3041         796 :     void GetGeometryParameters(EnergyPlusData &state, bool &ErrorsFound) // set to true if errors found during input
    3042             :     {
    3043             : 
    3044             :         // SUBROUTINE INFORMATION:
    3045             :         //       AUTHOR         Linda Lawrie
    3046             :         //       DATE WRITTEN   May 2000
    3047             :         //       MODIFIED       na
    3048             :         //       RE-ENGINEERED  na
    3049             : 
    3050             :         // PURPOSE OF THIS SUBROUTINE:
    3051             :         // This subroutine reads in the "Surface Geometry" parameters, verifies them,
    3052             :         // and sets "global" variables that will tell other routines how the surface
    3053             :         // vertices are expected in input.
    3054             : 
    3055             :         // METHODOLOGY EMPLOYED:
    3056             :         // na
    3057             : 
    3058             :         // REFERENCES:
    3059             :         // GlobalGeometryRules Definition
    3060             :         // GlobalGeometryRules,
    3061             :         //      \required-object
    3062             :         //      \unique-object
    3063             :         //  A1, \field Starting Vertex Position
    3064             :         //      \required-field
    3065             :         //      \note Specified as entry for a 4 sided surface/rectangle
    3066             :         //      \note Surfaces are specified as viewed from outside the surface
    3067             :         //      \note Shading surfaces as viewed from behind.  (towards what they are shading)
    3068             :         //      \type choice
    3069             :         //      \key UpperLeftCorner
    3070             :         //      \key LowerLeftCorner
    3071             :         //      \key UpperRightCorner
    3072             :         //      \key LowerRightCorner
    3073             :         //  A2, \field Vertex Entry Direction
    3074             :         //      \required-field
    3075             :         //      \type choice
    3076             :         //      \key Counterclockwise
    3077             :         //      \key Clockwise
    3078             :         //  A3, \field Coordinate System
    3079             :         //      \required-field
    3080             :         //      \note relative -- coordinates are entered relative to zone origin
    3081             :         //      \note world -- all coordinates entered are "absolute" for this facility
    3082             :         //      \note absolute -- same as world
    3083             :         //      \type choice
    3084             :         //      \key Relative
    3085             :         //      \key World
    3086             :         //      \key Absolute
    3087             :         //  A4, \field Daylighting Reference Point Coordinate System
    3088             :         //      \type choice
    3089             :         //      \key Relative
    3090             :         //      \default Relative
    3091             :         //      \note Relative -- coordinates are entered relative to zone origin
    3092             :         //      \key World
    3093             :         //      \note World -- all coordinates entered are "absolute" for this facility
    3094             :         //      \key Absolute
    3095             :         //      \note absolute -- same as world
    3096             :         //  A5; \field Rectangular Surface Coordinate System
    3097             :         //      \type choice
    3098             :         //      \key Relative
    3099             :         //      \default Relative
    3100             :         //      \note Relative -- Starting corner is entered relative to zone origin
    3101             :         //      \key World
    3102             :         //      \note World -- Starting corner is entered in "absolute"
    3103             :         //      \key Absolute
    3104             :         //      \note absolute -- same as world
    3105             : 
    3106             :         // Using/Aliasing
    3107             : 
    3108             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3109         796 :         static Array1D_string const FlCorners(4, {"UpperLeftCorner", "LowerLeftCorner", "LowerRightCorner", "UpperRightCorner"});
    3110             : 
    3111             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3112             :         int NumStmt;
    3113         796 :         Array1D_string GAlphas(5);
    3114             :         int NAlphas;
    3115         796 :         Array1D<Real64> GNum(1);
    3116             :         int NNum;
    3117             :         int IOStat;
    3118             :         bool OK;
    3119             :         int Found;
    3120         796 :         std::string OutMsg;
    3121             :         int ZoneNum; // For loop counter
    3122         796 :         bool RelWarning(false);
    3123         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3124             : 
    3125         796 :         cCurrentModuleObject = "GlobalGeometryRules";
    3126         796 :         NumStmt = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    3127         796 :         OutMsg = " Surface Geometry,";
    3128             : 
    3129             :         {
    3130         796 :             int const SELECT_CASE_var = NumStmt;
    3131             : 
    3132         796 :             if (SELECT_CASE_var == 1) {
    3133             :                 // This is the valid case
    3134        1592 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3135             :                                                                          cCurrentModuleObject,
    3136             :                                                                          1,
    3137             :                                                                          GAlphas,
    3138             :                                                                          NAlphas,
    3139             :                                                                          GNum,
    3140             :                                                                          NNum,
    3141             :                                                                          IOStat,
    3142         796 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3143         796 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3144         796 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3145         796 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3146             : 
    3147             :                 // Even though these will be validated, set defaults in case error here -- wont
    3148             :                 // cause aborts in later surface gets (hopefully)
    3149         796 :                 state.dataSurface->Corner = UpperLeftCorner;
    3150         796 :                 state.dataSurface->WorldCoordSystem = true;
    3151         796 :                 state.dataSurface->CCW = true;
    3152             : 
    3153         796 :                 OK = false;
    3154         796 :                 Found = Util::FindItem(GAlphas(1), FlCorners, 4);
    3155         796 :                 if (Found == 0) {
    3156           0 :                     ShowSevereError(state, format("{}: Invalid {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(1), GAlphas(1)));
    3157           0 :                     ErrorsFound = true;
    3158             :                 } else {
    3159         796 :                     state.dataSurface->Corner = Found;
    3160         796 :                     OK = true;
    3161         796 :                     OutMsg += FlCorners(state.dataSurface->Corner) + ',';
    3162             :                 }
    3163             : 
    3164         796 :                 OK = false;
    3165         796 :                 if (Util::SameString(GAlphas(2), "CCW") || Util::SameString(GAlphas(2), "Counterclockwise")) {
    3166         793 :                     state.dataSurface->CCW = true;
    3167         793 :                     OutMsg += "Counterclockwise,";
    3168         793 :                     OK = true;
    3169             :                 }
    3170         796 :                 if (Util::SameString(GAlphas(2), "CW") || Util::SameString(GAlphas(2), "Clockwise")) {
    3171           3 :                     state.dataSurface->CCW = false;
    3172           3 :                     OutMsg += "Clockwise,";
    3173           3 :                     OK = true;
    3174             :                 }
    3175         796 :                 if (!OK) {
    3176           0 :                     ShowSevereError(state, format("{}: Invalid {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(2), GAlphas(2)));
    3177           0 :                     ErrorsFound = true;
    3178             :                 }
    3179             : 
    3180         796 :                 OK = false;
    3181         796 :                 if (Util::SameString(GAlphas(3), "World") || Util::SameString(GAlphas(3), "Absolute")) {
    3182         357 :                     state.dataSurface->WorldCoordSystem = true;
    3183         357 :                     OutMsg += "WorldCoordinateSystem,";
    3184         357 :                     OK = true;
    3185             :                 }
    3186         796 :                 if (Util::SameString(GAlphas(3), "Relative")) {
    3187         439 :                     state.dataSurface->WorldCoordSystem = false;
    3188         439 :                     OutMsg += "RelativeCoordinateSystem,";
    3189         439 :                     OK = true;
    3190             :                 }
    3191         796 :                 if (!OK) {
    3192           0 :                     ShowWarningError(state, format("{}: Invalid {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(3), GAlphas(3)));
    3193           0 :                     ShowContinueError(state, format("{} defaults to \"WorldCoordinateSystem\"", state.dataIPShortCut->cAlphaFieldNames(3)));
    3194           0 :                     state.dataSurface->WorldCoordSystem = true;
    3195           0 :                     OutMsg += "WorldCoordinateSystem,";
    3196             :                 }
    3197             : 
    3198         796 :                 OK = false;
    3199         796 :                 if (Util::SameString(GAlphas(4), "World") || Util::SameString(GAlphas(4), "Absolute")) {
    3200           8 :                     state.dataSurface->DaylRefWorldCoordSystem = true;
    3201           8 :                     OutMsg += "WorldCoordinateSystem,";
    3202           8 :                     OK = true;
    3203             :                 }
    3204         796 :                 if (Util::SameString(GAlphas(4), "Relative") || GAlphas(4).empty()) {
    3205         788 :                     state.dataSurface->DaylRefWorldCoordSystem = false;
    3206         788 :                     OutMsg += "RelativeCoordinateSystem,";
    3207         788 :                     OK = true;
    3208             :                 }
    3209         796 :                 if (!OK) {
    3210           0 :                     ShowWarningError(state, format("{}: Invalid {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(4), GAlphas(4)));
    3211           0 :                     ShowContinueError(state, format("{} defaults to \"RelativeToZoneOrigin\"", state.dataIPShortCut->cAlphaFieldNames(4)));
    3212           0 :                     state.dataSurface->DaylRefWorldCoordSystem = false;
    3213           0 :                     OutMsg += "RelativeToZoneOrigin,";
    3214             :                 }
    3215             : 
    3216         796 :                 OK = false;
    3217         796 :                 if (Util::SameString(GAlphas(5), "World") || Util::SameString(GAlphas(5), "Absolute")) {
    3218          18 :                     state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = true;
    3219          18 :                     OutMsg += "WorldCoordinateSystem";
    3220          18 :                     OK = true;
    3221             :                 }
    3222         796 :                 if (Util::SameString(GAlphas(5), "Relative") || GAlphas(5).empty()) {
    3223         778 :                     state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = false;
    3224         778 :                     OutMsg += "RelativeToZoneOrigin";
    3225         778 :                     OK = true;
    3226             :                 }
    3227         796 :                 if (!OK) {
    3228           0 :                     ShowWarningError(state, format("{}: Invalid {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(5), GAlphas(5)));
    3229           0 :                     ShowContinueError(state, format("{} defaults to \"RelativeToZoneOrigin\"", state.dataIPShortCut->cAlphaFieldNames(5)));
    3230           0 :                     state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = false;
    3231           0 :                     OutMsg += "RelativeToZoneOrigin";
    3232             :                 }
    3233             : 
    3234           0 :             } else if (SELECT_CASE_var == 0) {
    3235             : 
    3236           0 :                 ShowSevereError(state, format("{}: Required object not found.", cCurrentModuleObject));
    3237           0 :                 OutMsg += "None found in input";
    3238           0 :                 ErrorsFound = true;
    3239             : 
    3240             :             } else {
    3241             : 
    3242           0 :                 ShowSevereError(state, format("{}: Too many objects entered.  Only one allowed.", cCurrentModuleObject));
    3243           0 :                 ErrorsFound = true;
    3244             :             }
    3245             :         }
    3246             : 
    3247         796 :         if (!state.dataSurface->WorldCoordSystem) {
    3248         439 :             if (state.dataSurface->DaylRefWorldCoordSystem) {
    3249           0 :                 ShowWarningError(state, format("{}: Potential mismatch of coordinate specifications.", cCurrentModuleObject));
    3250           0 :                 ShowContinueError(state, format("{}=\"{}\"; while ", state.dataIPShortCut->cAlphaFieldNames(3), GAlphas(3)));
    3251           0 :                 ShowContinueError(state, format("{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(4), GAlphas(4)));
    3252             :             }
    3253         439 :             if (state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem) {
    3254           0 :                 ShowWarningError(state, format("{}: Potential mismatch of coordinate specifications.", cCurrentModuleObject));
    3255           0 :                 ShowContinueError(state, format("{}=\"{}\"; while ", state.dataIPShortCut->cAlphaFieldNames(3), GAlphas(3)));
    3256           0 :                 ShowContinueError(state, format("{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(5), GAlphas(5)));
    3257             :             }
    3258             :         } else {
    3259         357 :             RelWarning = false;
    3260        1392 :             for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    3261        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginX != 0.0) RelWarning = true;
    3262        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginY != 0.0) RelWarning = true;
    3263        1035 :                 if (state.dataHeatBal->Zone(ZoneNum).OriginZ != 0.0) RelWarning = true;
    3264             :             }
    3265         357 :             if (RelWarning && !state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem) {
    3266           0 :                 ShowWarningError(state,
    3267           0 :                                  format("{}: Potential mismatch of coordinate specifications. Note that the rectangular surfaces are relying on the "
    3268             :                                         "default SurfaceGeometry for 'Relative to zone' coordinate.",
    3269             :                                         cCurrentModuleObject));
    3270           0 :                 ShowContinueError(state, format("{}=\"{}\"; while ", state.dataIPShortCut->cAlphaFieldNames(3), GAlphas(3)));
    3271           0 :                 if (GAlphas(5) == "RELATIVE") {
    3272           0 :                     ShowContinueError(state, format("{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(5), GAlphas(5)));
    3273           0 :                 } else if (GAlphas(5) != "ABSOLUTE") {
    3274           0 :                     ShowContinueError(state, format("{}=\"defaults to RELATIVE\".", state.dataIPShortCut->cAlphaFieldNames(5)));
    3275             :                 }
    3276             :             }
    3277             :         }
    3278             : 
    3279         796 :         print(state.files.eio,
    3280             :               "! <Surface Geometry>,Starting Corner,Vertex Input Direction,Coordinate System,Daylight Reference "
    3281             :               "Point Coordinate System,Rectangular (Simple) Surface Coordinate System\n");
    3282         796 :         print(state.files.eio, "{}\n", OutMsg);
    3283         796 :     }
    3284             : 
    3285         796 :     void GetDetShdSurfaceData(EnergyPlusData &state,
    3286             :                               bool &ErrorsFound,          // Error flag indicator (true if errors found)
    3287             :                               int &SurfNum,               // Count of Current SurfaceNumber
    3288             :                               int const TotDetachedFixed, // Number of Fixed Detached Shading Surfaces to obtain
    3289             :                               int const TotDetachedBldg   // Number of Building Detached Shading Surfaces to obtain
    3290             :     )
    3291             :     {
    3292             :         // SUBROUTINE INFORMATION:
    3293             :         //       AUTHOR         Linda Lawrie
    3294             :         //       DATE WRITTEN   May 2000
    3295             : 
    3296             :         // PURPOSE OF THIS SUBROUTINE:
    3297             :         // This subroutine gets the Detached Shading Surface Data,
    3298             :         // checks it for errors, etc.
    3299             : 
    3300             :         // Using/Aliasing
    3301             :         using ScheduleManager::CheckScheduleValueMinMax;
    3302             :         using ScheduleManager::GetScheduleIndex;
    3303             :         using ScheduleManager::GetScheduleMaxValue;
    3304             :         using ScheduleManager::GetScheduleMinValue;
    3305             : 
    3306             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3307         796 :         static Array1D_string const cModuleObjects(2, {"Shading:Site:Detailed", "Shading:Building:Detailed"});
    3308             : 
    3309             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3310             :         int IOStat;     // IO Status when calling get input subroutine
    3311             :         int NumAlphas;  // Number of material alpha names being passed
    3312             :         int NumNumbers; // Number of material properties being passed
    3313             :         int Loop;
    3314             :         int Item;
    3315             :         int ItemsToGet;
    3316             :         SurfaceClass ClassItem;
    3317             :         int numSides;
    3318             :         Real64 SchedMinValue;
    3319             :         Real64 SchedMaxValue;
    3320             : 
    3321         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3322             : 
    3323         796 :         if ((TotDetachedFixed + TotDetachedBldg) > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    3324           0 :             ShowWarningError(state, "Detached shading effects are ignored when Solar Distribution = MinimalShadowing");
    3325             :         }
    3326             : 
    3327         796 :         if ((TotDetachedFixed + TotDetachedBldg) == 0) return;
    3328             : 
    3329          60 :         for (Item = 1; Item <= 2; ++Item) {
    3330             : 
    3331          40 :             cCurrentModuleObject = cModuleObjects(Item);
    3332          40 :             if (Item == 1) {
    3333          20 :                 ItemsToGet = TotDetachedFixed;
    3334          20 :                 ClassItem = SurfaceClass::Detached_F;
    3335             :             } else { // IF (Item == 2) THEN
    3336          20 :                 ItemsToGet = TotDetachedBldg;
    3337          20 :                 ClassItem = SurfaceClass::Detached_B;
    3338             :             }
    3339             : 
    3340          40 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
    3341          40 :             if (NumAlphas != 2) {
    3342           0 :                 ShowSevereError(
    3343           0 :                     state, format("{}: Object Definition indicates not = 2 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
    3344           0 :                 ErrorsFound = true;
    3345             :             }
    3346             : 
    3347          96 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    3348         112 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3349             :                                                                          cCurrentModuleObject,
    3350             :                                                                          Loop,
    3351          56 :                                                                          state.dataIPShortCut->cAlphaArgs,
    3352             :                                                                          NumAlphas,
    3353          56 :                                                                          state.dataIPShortCut->rNumericArgs,
    3354             :                                                                          NumNumbers,
    3355             :                                                                          IOStat,
    3356          56 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3357          56 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3358          56 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3359          56 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3360             : 
    3361         112 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    3362          56 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    3363          56 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    3364             :                                                              cCurrentModuleObject,
    3365          56 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    3366             :                                                              ErrorsFound)) {
    3367           0 :                     continue;
    3368             :                 }
    3369             : 
    3370          56 :                 ++SurfNum;
    3371          56 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    3372          56 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = ClassItem;
    3373          56 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    3374          56 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
    3375             :                 // Base transmittance of a shadowing (sub)surface
    3376          56 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    3377             :                     // Schedule for a shadowing (sub)surface
    3378          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex =
    3379          26 :                         GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    3380          26 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex == 0) {
    3381           0 :                         ShowSevereError(state,
    3382           0 :                                         format("{}=\"{}\", {} not found={}",
    3383             :                                                cCurrentModuleObject,
    3384           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3385           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    3386           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
    3387           0 :                         ErrorsFound = true;
    3388             :                     }
    3389             :                 } else {
    3390          30 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    3391             :                 }
    3392          56 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex != 0) {
    3393          26 :                     if (!CheckScheduleValueMinMax(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex, ">=", 0.0, "<=", 1.0)) {
    3394           0 :                         ShowSevereError(state,
    3395           0 :                                         format("{}=\"{}\", {}=\"{}\", values not in range [0,1].",
    3396             :                                                cCurrentModuleObject,
    3397           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3398           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    3399           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
    3400           0 :                         ErrorsFound = true;
    3401             :                     }
    3402          26 :                     SchedMinValue = GetScheduleMinValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    3403          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue = SchedMinValue;
    3404          26 :                     SchedMaxValue = GetScheduleMaxValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    3405          26 :                     if (SchedMinValue == 1.0) {
    3406             :                         // Set transparent for now, check for EMS actuators later in SolarShading::resetShadingSurfaceTransparency
    3407           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent = true;
    3408             :                     }
    3409          26 :                     if (SchedMinValue < 0.0) {
    3410           0 :                         ShowSevereError(state,
    3411           0 :                                         format("{}=\"{}\", {}=\"{}\", has schedule values < 0.",
    3412             :                                                cCurrentModuleObject,
    3413           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3414           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    3415           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
    3416           0 :                         ShowContinueError(state, "...Schedule values < 0 have no meaning for shading elements.");
    3417             :                     }
    3418          26 :                     if (SchedMaxValue > 0.0) {
    3419          26 :                         state.dataSolarShading->anyScheduledShadingSurface = true;
    3420             :                     }
    3421          26 :                     if (SchedMaxValue > 1.0) {
    3422           0 :                         ShowSevereError(state,
    3423           0 :                                         format("{}=\"{}\", {}=\"{}\", has schedule values > 1.",
    3424             :                                                cCurrentModuleObject,
    3425           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3426           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    3427           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
    3428           0 :                         ShowContinueError(state, "...Schedule values > 1 have no meaning for shading elements.");
    3429             :                     }
    3430          26 :                     if (std::abs(SchedMinValue - SchedMaxValue) > Constant::OneMillionth) {
    3431           0 :                         state.dataSurface->ShadingTransmittanceVaries = true;
    3432             :                     }
    3433             :                 }
    3434          56 :                 if (state.dataIPShortCut->lNumericFieldBlanks(1) || state.dataIPShortCut->rNumericArgs(1) == Constant::AutoCalculate) {
    3435           0 :                     numSides = (NumNumbers - 1) / 3;
    3436           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = numSides;
    3437           0 :                     if (mod(NumNumbers - 1, 3) != 0) {
    3438           0 :                         ShowWarningError(state,
    3439           0 :                                          format("{}=\"{}\", {}",
    3440             :                                                 cCurrentModuleObject,
    3441           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3442           0 :                                                 format("{} not even multiple of 3. Will read in {}",
    3443           0 :                                                        state.dataIPShortCut->cNumericFieldNames(1),
    3444           0 :                                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    3445             :                     }
    3446           0 :                     if (numSides < 3) {
    3447           0 :                         ShowSevereError(state,
    3448           0 :                                         format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    3449             :                                                cCurrentModuleObject,
    3450           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3451           0 :                                                state.dataIPShortCut->cNumericFieldNames(1),
    3452           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    3453           0 :                         ErrorsFound = true;
    3454           0 :                         continue;
    3455             :                     }
    3456             :                 } else {
    3457          56 :                     numSides = (NumNumbers - 1) / 3;
    3458          56 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
    3459          56 :                     if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
    3460           0 :                         ShowWarningError(state,
    3461           0 :                                          format("{}=\"{}\", field {}={}",
    3462             :                                                 cCurrentModuleObject,
    3463           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3464           0 :                                                 state.dataIPShortCut->cNumericFieldNames(1),
    3465           0 :                                                 fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    3466           0 :                         ShowContinueError(state,
    3467           0 :                                           format("...but {} were entered. Only the indicated {} will be used.",
    3468             :                                                  numSides,
    3469           0 :                                                  state.dataIPShortCut->cNumericFieldNames(1)));
    3470             :                     }
    3471             :                 }
    3472          56 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    3473         168 :                 GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({2, _}));
    3474          56 :                 CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    3475          56 :                 if (state.dataReportFlag->MakeMirroredDetachedShading) {
    3476          56 :                     MakeMirrorSurface(state, SurfNum);
    3477             :                 }
    3478             :             }
    3479             : 
    3480             :         } // Item Loop
    3481             :     }
    3482             : 
    3483         796 :     void GetRectDetShdSurfaceData(EnergyPlusData &state,
    3484             :                                   bool &ErrorsFound,              // Error flag indicator (true if errors found)
    3485             :                                   int &SurfNum,                   // Count of Current SurfaceNumber
    3486             :                                   int const TotRectDetachedFixed, // Number of Fixed Detached Shading Surfaces to obtain
    3487             :                                   int const TotRectDetachedBldg   // Number of Building Detached Shading Surfaces to obtain
    3488             :     )
    3489             :     {
    3490             : 
    3491             :         // SUBROUTINE INFORMATION:
    3492             :         //       AUTHOR         Linda Lawrie
    3493             :         //       DATE WRITTEN   January 2009
    3494             :         //       MODIFIED       na
    3495             :         //       RE-ENGINEERED  na
    3496             : 
    3497             :         // PURPOSE OF THIS SUBROUTINE:
    3498             :         // Gets the simple, rectangular detached surfaces.
    3499             : 
    3500             :         // Using/Aliasing
    3501             : 
    3502             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3503         796 :         static Array1D_string const cModuleObjects(2, {"Shading:Site", "Shading:Building"});
    3504             : 
    3505             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3506             :         int IOStat;     // IO Status when calling get input subroutine
    3507             :         int NumAlphas;  // Number of material alpha names being passed
    3508             :         int NumNumbers; // Number of material properties being passed
    3509             :         int Loop;
    3510             :         int Item;
    3511             :         int ItemsToGet;
    3512             :         SurfaceClass ClassItem;
    3513             : 
    3514         796 :         if ((TotRectDetachedFixed + TotRectDetachedBldg) > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    3515           0 :             ShowWarningError(state, "Detached shading effects are ignored when Solar Distribution = MinimalShadowing");
    3516             :         }
    3517             : 
    3518         796 :         if (TotRectDetachedFixed + TotRectDetachedBldg == 0) return;
    3519           6 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3520          18 :         for (Item = 1; Item <= 2; ++Item) {
    3521             : 
    3522          12 :             cCurrentModuleObject = cModuleObjects(Item);
    3523          12 :             if (Item == 1) {
    3524           6 :                 ItemsToGet = TotRectDetachedFixed;
    3525           6 :                 ClassItem = SurfaceClass::Detached_F;
    3526             :             } else { // IF (Item == 2) THEN
    3527           6 :                 ItemsToGet = TotRectDetachedBldg;
    3528           6 :                 ClassItem = SurfaceClass::Detached_B;
    3529             :             }
    3530             : 
    3531          12 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
    3532          12 :             if (NumAlphas != 1) {
    3533           0 :                 ShowSevereError(
    3534           0 :                     state, format("{}: Object Definition indicates not = 1 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
    3535           0 :                 ErrorsFound = true;
    3536             :             }
    3537             : 
    3538          32 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    3539          40 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3540             :                                                                          cCurrentModuleObject,
    3541             :                                                                          Loop,
    3542          20 :                                                                          state.dataIPShortCut->cAlphaArgs,
    3543             :                                                                          NumAlphas,
    3544          20 :                                                                          state.dataIPShortCut->rNumericArgs,
    3545             :                                                                          NumNumbers,
    3546             :                                                                          IOStat,
    3547          20 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3548          20 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3549          20 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3550          20 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3551             : 
    3552          40 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    3553          20 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    3554          20 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    3555             :                                                              cCurrentModuleObject,
    3556          20 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    3557             :                                                              ErrorsFound)) {
    3558           0 :                     continue;
    3559             :                 }
    3560             : 
    3561          20 :                 ++SurfNum;
    3562          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    3563          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = ClassItem;
    3564          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    3565          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
    3566             : 
    3567          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataIPShortCut->rNumericArgs(1);
    3568          20 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B && !state.dataSurface->WorldCoordSystem) {
    3569           4 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingAzimuth;
    3570             :                 }
    3571          20 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    3572           6 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingRotationAppendixG;
    3573             :                 }
    3574          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataIPShortCut->rNumericArgs(2);
    3575          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    3576          20 :                     Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    3577             : 
    3578          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    3579          20 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    3580             : 
    3581         120 :                 MakeRectangularVertices(state,
    3582             :                                         SurfNum,
    3583          20 :                                         state.dataIPShortCut->rNumericArgs(3),
    3584          20 :                                         state.dataIPShortCut->rNumericArgs(4),
    3585          20 :                                         state.dataIPShortCut->rNumericArgs(5),
    3586          20 :                                         state.dataIPShortCut->rNumericArgs(6),
    3587          20 :                                         state.dataIPShortCut->rNumericArgs(7),
    3588          20 :                                         state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem);
    3589             : 
    3590          20 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    3591           0 :                     ShowSevereError(state,
    3592           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    3593             :                                            cCurrentModuleObject,
    3594           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3595           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    3596           0 :                     ErrorsFound = true;
    3597             :                 }
    3598             : 
    3599          20 :                 if (state.dataReportFlag->MakeMirroredDetachedShading) {
    3600          20 :                     MakeMirrorSurface(state, SurfNum);
    3601             :                 }
    3602             :             }
    3603             : 
    3604             :         } // Item Loop
    3605             :     }
    3606             : 
    3607         796 :     void GetHTSurfaceData(EnergyPlusData &state,
    3608             :                           bool &ErrorsFound,                 // Error flag indicator (true if errors found)
    3609             :                           int &SurfNum,                      // Count of Current SurfaceNumber
    3610             :                           int const TotHTSurfs,              // Number of Heat Transfer Base Surfaces to obtain
    3611             :                           int const TotDetailedWalls,        // Number of Wall:Detailed items to obtain
    3612             :                           int const TotDetailedRoofs,        // Number of RoofCeiling:Detailed items to obtain
    3613             :                           int const TotDetailedFloors,       // Number of Floor:Detailed items to obtain
    3614             :                           const Array1D_string &BaseSurfCls, // Valid Classes for Base Surfaces
    3615             :                           const Array1D<SurfaceClass> &BaseSurfIDs,
    3616             :                           int &NeedToAddSurfaces // Number of surfaces to add, based on unentered IZ surfaces
    3617             :     )
    3618             :     {
    3619             : 
    3620             :         // SUBROUTINE INFORMATION:
    3621             :         //       AUTHOR         Linda Lawrie
    3622             :         //       DATE WRITTEN   May 2000
    3623             :         //       MODIFIED       na
    3624             :         //       RE-ENGINEERED  na
    3625             : 
    3626             :         // PURPOSE OF THIS SUBROUTINE:
    3627             :         // This subroutine gets the HeatTransfer Surface Data,
    3628             :         // checks it for errors, etc.
    3629             : 
    3630             :         // METHODOLOGY EMPLOYED:
    3631             :         // na
    3632             : 
    3633             :         // REFERENCES:
    3634             :         // Heat Transfer Surface Definition
    3635             :         // BuildingSurface:Detailed,
    3636             :         //  \extensible:3 -- duplicate last set of x,y,z coordinates (last 3 fields), remembering to remove ; from "inner" fields.
    3637             :         //  \format vertices
    3638             :         //  A1 , \field Name
    3639             :         //       \required-field
    3640             :         //       \type alpha
    3641             :         //       \reference SurfaceNames
    3642             :         //       \reference SurfAndSubSurfNames
    3643             :         //       \reference AllHeatTranSurfNames
    3644             :         //       \reference HeatTranBaseSurfNames
    3645             :         //       \reference OutFaceEnvNames
    3646             :         //       \reference AllHeatTranAngFacNames
    3647             :         //       \reference RadGroupAndSurfNames
    3648             :         //       \reference SurfGroupAndHTSurfNames
    3649             :         //       \reference AllShadingAndHTSurfNames
    3650             :         //  A2 , \field Surface Type
    3651             :         //       \required-field
    3652             :         //       \type choice
    3653             :         //       \key Floor
    3654             :         //       \key Wall
    3655             :         //       \key Ceiling
    3656             :         //       \key Roof
    3657             :         //  A3 , \field Construction Name
    3658             :         //       \required-field
    3659             :         //       \note To be matched with a construction in this input file
    3660             :         //       \type object-list
    3661             :         //       \object-list ConstructionNames
    3662             :         //  A4 , \field Zone Name
    3663             :         //       \required-field
    3664             :         //       \note Zone the surface is a part of
    3665             :         //       \type object-list
    3666             :         //       \object-list ZoneNames
    3667             :         //  A5 , \field Outside Boundary Condition
    3668             :         //       \required-field
    3669             :         //       \type choice
    3670             :         //       \key Adiabatic
    3671             :         //       \key Surface
    3672             :         //       \key Zone
    3673             :         //       \key Outdoors
    3674             :         //       \key Ground
    3675             :         //       \key GroundFCfactorMethod
    3676             :         //       \key OtherSideCoefficients
    3677             :         //       \key OtherSideConditionsModel
    3678             :         //       \key GroundSlabPreprocessorAverage
    3679             :         //       \key GroundSlabPreprocessorCore
    3680             :         //       \key GroundSlabPreprocessorPerimeter
    3681             :         //       \key GroundBasementPreprocessorAverageWall
    3682             :         //       \key GroundBasementPreprocessorAverageFloor
    3683             :         //       \key GroundBasementPreprocessorUpperWall
    3684             :         //       \key GroundBasementPreprocessorLowerWall
    3685             :         //  A6,  \field Outside Boundary Condition Object
    3686             :         //       \type object-list
    3687             :         //       \object-list OutFaceEnvNames
    3688             :         //       \note Non-blank only if the field Outside Boundary Condition is Surface,
    3689             :         //       \note Zone, OtherSideCoefficients or OtherSideConditionsModel
    3690             :         //       \note If Surface, specify name of corresponding surface in adjacent zone or
    3691             :         //       \note specify current surface name for internal partition separating like zones
    3692             :         //       \note If Zone, specify the name of the corresponding zone and
    3693             :         //       \note the program will generate the corresponding interzone surface
    3694             :         //       \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
    3695             :         //       \note If OtherSideConditionsModel, specify name of SurfaceProperty:OtherSideConditionsModel
    3696             :         //  A7 , \field Sun Exposure
    3697             :         //       \required-field
    3698             :         //       \type choice
    3699             :         //       \key SunExposed
    3700             :         //       \key NoSun
    3701             :         //       \default SunExposed
    3702             :         //  A8,  \field Wind Exposure
    3703             :         //       \required-field
    3704             :         //       \type choice
    3705             :         //       \key WindExposed
    3706             :         //       \key NoWind
    3707             :         //       \default WindExposed
    3708             :         //  N1,  \field View Factor to Ground
    3709             :         //       \type real
    3710             :         //       \note From the exterior of the surface
    3711             :         //       \note Unused if one uses the "reflections" options in Solar Distribution in Building input
    3712             :         //       \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
    3713             :         //       \note autocalculate will automatically calculate this value from the tilt of the surface
    3714             :         //       \autocalculatable
    3715             :         //       \minimum 0.0
    3716             :         //       \maximum 1.0
    3717             :         //       \default autocalculate
    3718             :         //  N2 , \field Number of Vertices
    3719             :         //       \note shown with 120 vertex coordinates -- extensible object
    3720             :         //       \note  "extensible" -- duplicate last set of x,y,z coordinates (last 3 fields),
    3721             :         //       \note remembering to remove ; from "inner" fields.
    3722             :         //       \note for clarity in any error messages, renumber the fields as well.
    3723             :         //       \note (and changing z terminator to a comma "," for all but last one which needs a semi-colon ";")
    3724             :         //       \autocalculatable
    3725             :         //       \minimum 3
    3726             :         //       \default autocalculate
    3727             :         //       \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
    3728             :         //       \note are "relative" to the Zone Origin.  If world, then building and zone origins are used
    3729             :         //       \note for some internal calculations, but all coordinates are given in an "absolute" system.
    3730             :         //  N3-xx as indicated by the N3 value
    3731             : 
    3732             :         // Using/Aliasing
    3733             : 
    3734             :         // SUBROUTINE PARAMETER DEFINITIONS:
    3735         796 :         static Array1D_string const cModuleObjects(4, {"BuildingSurface:Detailed", "Wall:Detailed", "Floor:Detailed", "RoofCeiling:Detailed"});
    3736             : 
    3737             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3738             :         int IOStat;          // IO Status when calling get input subroutine
    3739             :         int SurfaceNumAlpha; // Number of material alpha names being passed
    3740             :         int SurfaceNumProp;  // Number of material properties being passed
    3741             :         int ZoneNum;         // DO loop counter (zones)
    3742             :         int Found;           // For matching interzone surfaces
    3743             :         int Loop;
    3744             :         int Item;
    3745             :         int ItemsToGet;
    3746             :         int ClassItem;
    3747             :         int ArgPointer;
    3748             :         int numSides;
    3749             : 
    3750         796 :         GetOSCData(state, ErrorsFound);
    3751         796 :         GetOSCMData(state, ErrorsFound);
    3752         796 :         GetFoundationData(state, ErrorsFound);
    3753             : 
    3754         796 :         NeedToAddSurfaces = 0;
    3755         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    3756        3980 :         for (Item = 1; Item <= 4; ++Item) {
    3757             : 
    3758        3184 :             cCurrentModuleObject = cModuleObjects(Item);
    3759        3184 :             if (Item == 1) {
    3760         796 :                 ItemsToGet = TotHTSurfs;
    3761         796 :                 ClassItem = 0;
    3762        2388 :             } else if (Item == 2) {
    3763         796 :                 ItemsToGet = TotDetailedWalls;
    3764         796 :                 ClassItem = 1;
    3765        1592 :             } else if (Item == 3) {
    3766         796 :                 ItemsToGet = TotDetailedFloors;
    3767         796 :                 ClassItem = 2;
    3768             :             } else { // IF (Item == 4) THEN
    3769         796 :                 ItemsToGet = TotDetailedRoofs;
    3770         796 :                 ClassItem = 3;
    3771             :             }
    3772             : 
    3773        3184 :             state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, SurfaceNumAlpha, SurfaceNumProp);
    3774        3184 :             if (Item == 1) {
    3775         796 :                 if (SurfaceNumAlpha != 9) {
    3776           0 :                     ShowSevereError(
    3777             :                         state,
    3778           0 :                         format("{}: Object Definition indicates not = 9 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    3779           0 :                     ErrorsFound = true;
    3780             :                 }
    3781             :             } else {
    3782        2388 :                 if (SurfaceNumAlpha != 8) {
    3783           0 :                     ShowSevereError(
    3784             :                         state,
    3785           0 :                         format("{}: Object Definition indicates not = 8 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    3786           0 :                     ErrorsFound = true;
    3787             :                 }
    3788             :             }
    3789             : 
    3790       38011 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    3791       69654 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3792             :                                                                          cCurrentModuleObject,
    3793             :                                                                          Loop,
    3794       34827 :                                                                          state.dataIPShortCut->cAlphaArgs,
    3795             :                                                                          SurfaceNumAlpha,
    3796       34827 :                                                                          state.dataIPShortCut->rNumericArgs,
    3797             :                                                                          SurfaceNumProp,
    3798             :                                                                          IOStat,
    3799       34827 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    3800       34827 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    3801       34827 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    3802       34827 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    3803             : 
    3804       69654 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    3805       34827 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    3806       34827 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    3807             :                                                              cCurrentModuleObject,
    3808       34827 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    3809             :                                                              ErrorsFound)) {
    3810           0 :                     continue;
    3811             :                 }
    3812             : 
    3813       34827 :                 ++SurfNum;
    3814       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    3815       34827 :                 ArgPointer = 2;
    3816       34827 :                 if (Item == 1) {
    3817       34803 :                     if (state.dataIPShortCut->cAlphaArgs(2) == "CEILING") state.dataIPShortCut->cAlphaArgs(2) = "ROOF";
    3818       34803 :                     ClassItem = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), BaseSurfCls, 3);
    3819       34803 :                     if (ClassItem == 0) {
    3820           0 :                         ShowSevereError(state,
    3821           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
    3822             :                                                cCurrentModuleObject,
    3823           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3824           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    3825           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
    3826           0 :                         ErrorsFound = true;
    3827             :                     } else {
    3828       34803 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);
    3829             :                     }
    3830       34803 :                     ++ArgPointer;
    3831             :                 } else {
    3832          24 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);
    3833             :                 }
    3834             : 
    3835       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = Util::FindItemInList(
    3836       34827 :                     state.dataIPShortCut->cAlphaArgs(ArgPointer), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    3837             : 
    3838       34827 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    3839           0 :                     ErrorsFound = true;
    3840           0 :                     ShowSevereError(state,
    3841           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    3842             :                                            cCurrentModuleObject,
    3843           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3844           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    3845           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    3846       34827 :                 } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    3847           0 :                     ErrorsFound = true;
    3848           0 :                     ShowSevereError(state,
    3849           0 :                                     format("{}=\"{}\", invalid {}=\"{}\" - has Window materials.",
    3850             :                                            cCurrentModuleObject,
    3851           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3852           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    3853           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    3854           0 :                     if (Item == 1) {
    3855           0 :                         ShowContinueError(state,
    3856           0 :                                           format("...because {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
    3857             :                     } else {
    3858           0 :                         ShowContinueError(state, format("...because Surface Type={}", BaseSurfCls(ClassItem)));
    3859             :                     }
    3860             :                 } else {
    3861       34827 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    3862       34827 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    3863       34827 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    3864             :                 }
    3865       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    3866       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
    3867       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    3868             : 
    3869       34827 :                 ++ArgPointer;
    3870       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataIPShortCut->cAlphaArgs(ArgPointer);
    3871       34827 :                 ZoneNum = Util::FindItemInList(
    3872       34827 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    3873             : 
    3874       34827 :                 if (ZoneNum != 0) {
    3875       34827 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
    3876             :                 } else {
    3877           0 :                     ShowSevereError(state,
    3878           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    3879             :                                            cCurrentModuleObject,
    3880           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3881           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    3882           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    3883           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    3884           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    3885           0 :                     ErrorsFound = true;
    3886             :                 }
    3887             : 
    3888       34827 :                 ++ArgPointer;
    3889       34827 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer)) {
    3890          63 :                     int spaceNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(ArgPointer), state.dataHeatBal->space);
    3891             : 
    3892          63 :                     if (spaceNum != 0) {
    3893          63 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
    3894          63 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone != state.dataHeatBal->space(spaceNum).zoneNum) {
    3895           0 :                             ShowSevereError(state,
    3896           0 :                                             format("{}=\"{}\", invalid {}=\"{}\" is not in the same zone as the surface.",
    3897             :                                                    cCurrentModuleObject,
    3898           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3899           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    3900           0 :                                                    state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    3901           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    3902           0 :                             ErrorsFound = true;
    3903             :                         }
    3904             :                     } else {
    3905           0 :                         ShowSevereError(state,
    3906           0 :                                         format("{}=\"{}\", invalid {}=\"{}\" not found.",
    3907             :                                                cCurrentModuleObject,
    3908           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3909           0 :                                                state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    3910           0 :                                                state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    3911           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    3912           0 :                         ErrorsFound = true;
    3913             :                     }
    3914             :                 }
    3915             :                 // Get the ExteriorBoundaryCondition flag from input There are 4 conditions that
    3916             :                 // can take place. The conditions are set with a 0, -1, or -2, or all of the
    3917             :                 // zone names have to be looked at and generate the interzone array number
    3918       34827 :                 ++ArgPointer;
    3919       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(ArgPointer + 1);
    3920             : 
    3921       34827 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Outdoors")) {
    3922       11130 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    3923             : 
    3924       23697 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Adiabatic")) {
    3925        1270 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    3926        1270 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    3927             : 
    3928       22427 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Ground")) {
    3929        2194 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = Ground;
    3930             : 
    3931        2194 :                     if (state.dataSurfaceGeometry->NoGroundTempObjWarning) {
    3932         436 :                         if (!state.dataEnvrn->GroundTempInputs[(int)DataEnvironment::GroundTempType::BuildingSurface]) {
    3933           2 :                             ShowWarningError(state,
    3934             :                                              "GetHTSurfaceData: Surfaces with interface to Ground found but no \"Ground Temperatures\" were input.");
    3935           2 :                             ShowContinueError(state, format("Found first in surface={}", state.dataIPShortCut->cAlphaArgs(1)));
    3936           4 :                             ShowContinueError(state,
    3937           4 :                                               format("Defaults, constant throughout the year of ({:.1R}) will be used.",
    3938           2 :                                                      state.dataEnvrn->GroundTemp[(int)DataEnvironment::GroundTempType::BuildingSurface]));
    3939             :                         }
    3940         436 :                         state.dataSurfaceGeometry->NoGroundTempObjWarning = false;
    3941             :                     }
    3942             : 
    3943             :                     // Added for FCfactor method
    3944       20233 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundFCfactorMethod")) {
    3945         184 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
    3946         184 :                     if (state.dataSurfaceGeometry->NoFCGroundTempObjWarning) {
    3947         184 :                         if (!state.dataEnvrn->GroundTempInputs[(int)DataEnvironment::GroundTempType::FCFactorMethod]) {
    3948           0 :                             ShowSevereError(state,
    3949             :                                             "GetHTSurfaceData: Surfaces with interface to GroundFCfactorMethod found but no \"FC Ground "
    3950             :                                             "Temperatures\" were input.");
    3951           0 :                             ShowContinueError(state, format("Found first in surface={}", state.dataIPShortCut->cAlphaArgs(1)));
    3952           0 :                             ShowContinueError(state,
    3953             :                                               "Either add a \"Site:GroundTemperature:FCfactorMethod\" object or use a weather file with "
    3954             :                                               "Ground Temperatures.");
    3955           0 :                             ErrorsFound = true;
    3956           0 :                             state.dataSurfaceGeometry->NoFCGroundTempObjWarning = false;
    3957             :                         }
    3958             :                     }
    3959         184 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
    3960         218 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    3961          34 :                             !state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
    3962           0 :                             ShowSevereError(state,
    3963           0 :                                             format("{}=\"{}\", invalid {}",
    3964             :                                                    cCurrentModuleObject,
    3965           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3966           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(ArgPointer)));
    3967           0 :                             ShowContinueError(
    3968             :                                 state,
    3969           0 :                                 format("Construction=\"{}\" is not type Construction:CfactorUndergroundWall.",
    3970           0 :                                        state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name));
    3971           0 :                             ErrorsFound = true;
    3972             :                         }
    3973         334 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    3974         150 :                             !state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
    3975           0 :                             ShowSevereError(state,
    3976           0 :                                             format("{}=\"{}\", invalid {}",
    3977             :                                                    cCurrentModuleObject,
    3978           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3979           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(ArgPointer)));
    3980           0 :                             ShowContinueError(
    3981             :                                 state,
    3982           0 :                                 format("Construction=\"{}\" is not type Construction:FfactorGroundFloor.",
    3983           0 :                                        state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name));
    3984           0 :                             ErrorsFound = true;
    3985             :                         }
    3986             :                     }
    3987             : 
    3988       20049 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "OtherSideCoefficients")) {
    3989          17 :                     Found = Util::FindItemInList(
    3990          17 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataSurface->OSC, state.dataSurface->TotOSC);
    3991          17 :                     if (Found == 0) {
    3992           0 :                         ShowSevereError(state,
    3993           0 :                                         format("{}=\"{}\", invalid {}=\"{}\".",
    3994             :                                                cCurrentModuleObject,
    3995           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    3996           0 :                                                state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1),
    3997           0 :                                                state.dataIPShortCut->cAlphaArgs(ArgPointer + 1)));
    3998           0 :                         ShowContinueError(state, " no OtherSideCoefficients of that name.");
    3999           0 :                         ErrorsFound = true;
    4000             :                     } else {
    4001          17 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
    4002          17 :                         if (state.dataSurface->OSC(Found).SurfFilmCoef > 0.0) {
    4003           1 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefCalcExt;
    4004             :                         } else {
    4005          16 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefNoCalcExt;
    4006             :                         }
    4007             :                     }
    4008             : 
    4009       20032 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Surface")) {
    4010             :                     // it has to be another surface which needs to be found
    4011             :                     // this will be found on the second pass through the surface input
    4012             :                     // for flagging, set the value to UnreconciledZoneSurface
    4013             :                     // name (ExtBoundCondName) will be validated later.
    4014       19574 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    4015       19574 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer + 1)) {
    4016           6 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    4017          12 :                         ShowSevereError(state,
    4018          18 :                                         format("{}=\"{}\", invalid {}=<blank>.",
    4019             :                                                cCurrentModuleObject,
    4020           6 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4021           6 :                                                state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1)));
    4022           6 :                         ShowContinueError(state, format("..{}=\"Surface\" must be non-blank.", state.dataIPShortCut->cAlphaFieldNames(ArgPointer)));
    4023           6 :                         ShowContinueError(state, "..This surface will become an adiabatic surface - no doors/windows allowed.");
    4024             :                     }
    4025             : 
    4026         458 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Zone")) {
    4027             :                     // This is the code for an unmatched "other surface"
    4028             :                     // will be set up later.
    4029         365 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    4030             :                     // check OutsideFaceEnvironment for legal zone
    4031         365 :                     Found = Util::FindItemInList(
    4032         365 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    4033         365 :                     ++NeedToAddSurfaces;
    4034             : 
    4035         365 :                     if (Found == 0) {
    4036           0 :                         ShowSevereError(state,
    4037           0 :                                         format("{}=\"{}\", invalid {}=\"{}\".",
    4038             :                                                cCurrentModuleObject,
    4039           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4040           0 :                                                state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    4041           0 :                                                state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    4042           0 :                         ShowContinueError(state, "..Referenced as Zone for this surface.");
    4043           0 :                         ErrorsFound = true;
    4044             :                     }
    4045             : 
    4046          93 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Foundation")) {
    4047             : 
    4048          38 :                     if (!state.dataWeather->WeatherFileExists) {
    4049           0 :                         ShowSevereError(
    4050             :                             state,
    4051           0 :                             format("{}=\"{}\", using \"Foundation\" type Outside Boundary Condition requires specification of a weather file",
    4052             :                                    cCurrentModuleObject,
    4053           0 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    4054           0 :                         ShowContinueError(state,
    4055             :                                           "Either place in.epw in the working directory or specify a weather file on the command line using -w "
    4056             :                                           "/path/to/weather.epw");
    4057           0 :                         ErrorsFound = true;
    4058             :                     }
    4059             : 
    4060             :                     // Find foundation object, if blank use default
    4061          38 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer + 1)) {
    4062             : 
    4063           8 :                         if (!state.dataSurfaceGeometry->kivaManager.defaultAdded) {
    4064             :                             // Add default foundation if no other foundation object specified
    4065           2 :                             state.dataSurfaceGeometry->kivaManager.addDefaultFoundation();
    4066             :                         }
    4067           8 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr =
    4068           8 :                             state.dataSurfaceGeometry->kivaManager.defaultIndex; // Reuse OSC pointer...shouldn't be used for non OSC surfaces anyway.
    4069             :                     } else {
    4070             :                         Found =
    4071          30 :                             state.dataSurfaceGeometry->kivaManager.findFoundation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName);
    4072          30 :                         if (Found != (int)state.dataSurfaceGeometry->kivaManager.foundationInputs.size()) {
    4073          30 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
    4074             :                         } else {
    4075           0 :                             ShowSevereError(state,
    4076           0 :                                             format("{}=\"{}\", invalid {}=\"{}\".",
    4077             :                                                    cCurrentModuleObject,
    4078           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    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 :                                         format("{}=\"{}\", construction may not have an internal source/sink",
    4088             :                                                cCurrentModuleObject,
    4089           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    4090           0 :                         ErrorsFound = true;
    4091             :                     }
    4092          38 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = KivaFoundation;
    4093             : 
    4094          55 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "OtherSideConditionsModel")) {
    4095          55 :                     Found = Util::FindItemInList(
    4096          55 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataSurface->OSCM, state.dataSurface->TotOSCM);
    4097          55 :                     if (Found == 0) {
    4098           0 :                         ShowSevereError(state,
    4099           0 :                                         format("{}=\"{}\", invalid {}=\"{}\".",
    4100             :                                                cCurrentModuleObject,
    4101           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4102           0 :                                                state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1),
    4103           0 :                                                state.dataIPShortCut->cAlphaArgs(ArgPointer + 1)));
    4104           0 :                         ErrorsFound = true;
    4105             :                     }
    4106          55 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCMPtr = Found;
    4107          55 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCondModeledExt;
    4108             : 
    4109           0 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorAverage") ||
    4110           0 :                            Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorCore") ||
    4111           0 :                            Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorPerimeter") ||
    4112           0 :                            Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorAverageFloor") ||
    4113           0 :                            Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorAverageWall") ||
    4114           0 :                            Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorUpperWall") ||
    4115           0 :                            Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorLowerWall")) {
    4116           0 :                     ShowSevereError(state,
    4117           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    4118             :                                            cCurrentModuleObject,
    4119           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4120           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    4121           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    4122           0 :                     ShowContinueError(state, "The ExpandObjects program has not been run or is not in your EnergyPlus.exe folder.");
    4123           0 :                     ErrorsFound = true;
    4124             : 
    4125             :                 } else {
    4126           0 :                     ShowSevereError(state,
    4127           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    4128             :                                            cCurrentModuleObject,
    4129           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4130           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    4131           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    4132           0 :                     ShowContinueError(state,
    4133             :                                       "Should be one of \"Outdoors\", \"Adiabatic\", Ground\", \"Surface\", \"OtherSideCoefficients\", "
    4134             :                                       "\"OtherSideConditionsModel\" or \"Zone\"");
    4135           0 :                     ErrorsFound = true;
    4136             :                 } // ... End of the ExtBoundCond logical IF Block
    4137             : 
    4138       34827 :                 ArgPointer += 2;
    4139             :                 // Set the logical flag for the exterior solar
    4140       34827 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "SunExposed")) {
    4141       11064 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment) &&
    4142          29 :                         (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != OtherSideCondModeledExt)) {
    4143           0 :                         ShowWarningError(state,
    4144           0 :                                          format("{}=\"{}\", {}=\"{}\".",
    4145             :                                                 cCurrentModuleObject,
    4146           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4147           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    4148           0 :                                                 state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    4149           0 :                         ShowContinueError(state, "..This surface is not exposed to External Environment.  Sun exposure has no effect.");
    4150             :                     } else {
    4151       11035 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
    4152             :                     }
    4153       23792 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "NoSun")) {
    4154       23792 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
    4155             :                 } else {
    4156           0 :                     ShowSevereError(state,
    4157           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    4158             :                                            cCurrentModuleObject,
    4159           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4160           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    4161           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    4162           0 :                     ErrorsFound = true;
    4163             :                 }
    4164             : 
    4165       34827 :                 ++ArgPointer;
    4166             :                 // Set the logical flag for the exterior wind
    4167       34827 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "WindExposed")) {
    4168       11103 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = true;
    4169       23724 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "NoWind")) {
    4170       23724 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
    4171             :                 } else {
    4172           0 :                     ShowSevereError(state,
    4173           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    4174             :                                            cCurrentModuleObject,
    4175           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4176           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ArgPointer),
    4177           0 :                                            state.dataIPShortCut->cAlphaArgs(ArgPointer)));
    4178           0 :                     ErrorsFound = true;
    4179             :                 }
    4180             : 
    4181             :                 // Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
    4182             :                 //                if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0)
    4183             :                 //                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof =
    4184             :                 //                        state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof;
    4185             : 
    4186       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataIPShortCut->rNumericArgs(1);
    4187       34827 :                 if (state.dataIPShortCut->lNumericFieldBlanks(1))
    4188         641 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = Constant::AutoCalculate;
    4189       34827 :                 if (state.dataIPShortCut->lNumericFieldBlanks(2) || state.dataIPShortCut->rNumericArgs(2) == Constant::AutoCalculate) {
    4190         750 :                     numSides = (SurfaceNumProp - 2) / 3;
    4191         750 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = numSides;
    4192         750 :                     if (mod(SurfaceNumProp - 2, 3) != 0) {
    4193           0 :                         ShowWarningError(state,
    4194           0 :                                          format("{}=\"{}\", {}",
    4195             :                                                 cCurrentModuleObject,
    4196           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4197           0 :                                                 format("{} not even multiple of 3. Will read in {}",
    4198           0 :                                                        state.dataIPShortCut->cNumericFieldNames(2),
    4199           0 :                                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    4200             :                     }
    4201         750 :                     if (numSides < 3) {
    4202           0 :                         ShowSevereError(state,
    4203           0 :                                         format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    4204             :                                                cCurrentModuleObject,
    4205           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4206           0 :                                                state.dataIPShortCut->cNumericFieldNames(2),
    4207           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    4208           0 :                         ErrorsFound = true;
    4209           0 :                         continue;
    4210             :                     }
    4211             :                 } else {
    4212       34077 :                     numSides = (SurfaceNumProp - 2) / 3;
    4213       34077 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(2);
    4214       34077 :                     if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
    4215           0 :                         ShowWarningError(state,
    4216           0 :                                          format("{}=\"{}\", field {}={}",
    4217             :                                                 cCurrentModuleObject,
    4218           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4219           0 :                                                 state.dataIPShortCut->cNumericFieldNames(2),
    4220           0 :                                                 fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    4221           0 :                         ShowContinueError(state,
    4222           0 :                                           format("...but {} were entered. Only the indicated {} will be used.",
    4223             :                                                  numSides,
    4224           0 :                                                  state.dataIPShortCut->cNumericFieldNames(2)));
    4225             :                     }
    4226             :                 }
    4227       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4228       34827 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewVertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4229      104481 :                 GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({3, _}));
    4230       34827 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    4231           0 :                     ShowSevereError(state,
    4232           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    4233             :                                            cCurrentModuleObject,
    4234           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4235           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4236           0 :                     ErrorsFound = true;
    4237             :                 }
    4238             : 
    4239       34827 :                 CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4240       34827 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), "Surface")) {
    4241          16 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides !=
    4242           8 :                         static_cast<int>(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.size())) {
    4243           0 :                         ShowSevereError(state,
    4244           0 :                                         format("{}=\"{}\", After CheckConvexity, mismatch between Sides ({}) and size of Vertex ({}).",
    4245             :                                                cCurrentModuleObject,
    4246           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4247           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4248           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.size()));
    4249           0 :                         ShowContinueError(state, "CheckConvexity is used to verify the convexity of a surface and detect collinear points.");
    4250           0 :                         ErrorsFound = true;
    4251             :                     }
    4252             :                 }
    4253       34827 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
    4254             :                     // Check wall height for the CFactor walls
    4255             : 
    4256       57115 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    4257       22288 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
    4258          34 :                         if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height -
    4259          34 :                                      state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Height) > 0.05) {
    4260           0 :                             ShowWarningError(state,
    4261           0 :                                              format("{}=\"{}\", underground Wall Height = {:.2T}",
    4262             :                                                     cCurrentModuleObject,
    4263           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4264           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height));
    4265           0 :                             ShowContinueError(state, "..which does not match its construction height.");
    4266             :                         }
    4267             :                     }
    4268             : 
    4269             :                     // Check area and perimeter for the FFactor floors
    4270       41601 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    4271        6774 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
    4272         184 :                         if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area -
    4273         184 :                                      state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Area) > 0.1) {
    4274           0 :                             ShowWarningError(state,
    4275           0 :                                              format("{}=\"{}\", underground Floor Area = {:.2T}",
    4276             :                                                     cCurrentModuleObject,
    4277           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4278           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4279           0 :                             ShowContinueError(state, "..which does not match its construction area.");
    4280             :                         }
    4281         184 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter <
    4282         184 :                             state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).PerimeterExposed - 0.1) {
    4283           0 :                             ShowWarningError(state,
    4284           0 :                                              format("{}=\"{}\", underground Floor Perimeter = {:.2T}",
    4285             :                                                     cCurrentModuleObject,
    4286           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4287           0 :                                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter));
    4288           0 :                             ShowContinueError(state, "..which is less than its construction exposed perimeter.");
    4289             :                         }
    4290             :                     }
    4291             :                 }
    4292             :             }
    4293             :         } // Item Looop
    4294             :         // Check number of Vertex between base surface and Outside Boundary surface
    4295             :         int ExtSurfNum;
    4296       35775 :         for (int i = 1; i <= SurfNum; i++) {
    4297       55823 :             if (state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCond == UnreconciledZoneSurface &&
    4298       20844 :                 state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName != "") {
    4299       20844 :                 ExtSurfNum = Util::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName, state.dataSurfaceGeometry->SurfaceTmp);
    4300             :                 // If we cannot find the referenced surface
    4301       20844 :                 if (ExtSurfNum == 0) {
    4302           0 :                     ShowSevereError(state,
    4303           0 :                                     format("{}=\"{}\" references an outside boundary surface that cannot be found:{}",
    4304             :                                            cCurrentModuleObject,
    4305           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(i).Name,
    4306           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName));
    4307           0 :                     ErrorsFound = true;
    4308             :                     // If vertex size mistmatch
    4309       41688 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(i).Vertex.size() !=
    4310       20844 :                            state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Vertex.size()) {
    4311           0 :                     ShowSevereError(state,
    4312           0 :                                     format("{}=\"{}\", Vertex size mismatch between base surface :{} and outside boundary surface: {}",
    4313             :                                            cCurrentModuleObject,
    4314           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(i).Name,
    4315           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(i).Name,
    4316           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Name));
    4317           0 :                     ShowContinueError(state,
    4318           0 :                                       format("The vertex sizes are {} for base surface and {} for outside boundary surface. Please check inputs.",
    4319           0 :                                              state.dataSurfaceGeometry->SurfaceTmp(i).Vertex.size(),
    4320           0 :                                              state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Vertex.size()));
    4321           0 :                     ErrorsFound = true;
    4322             :                 }
    4323             :             }
    4324             :         }
    4325         796 :     }
    4326             : 
    4327         796 :     void GetRectSurfaces(EnergyPlusData &state,
    4328             :                          bool &ErrorsFound,                        // Error flag indicator (true if errors found)
    4329             :                          int &SurfNum,                             // Count of Current SurfaceNumber
    4330             :                          int const TotRectExtWalls,                // Number of Exterior Walls to obtain
    4331             :                          int const TotRectIntWalls,                // Number of Adiabatic Walls to obtain
    4332             :                          int const TotRectIZWalls,                 // Number of Interzone Walls to obtain
    4333             :                          int const TotRectUGWalls,                 // Number of Underground to obtain
    4334             :                          int const TotRectRoofs,                   // Number of Roofs to obtain
    4335             :                          int const TotRectCeilings,                // Number of Adiabatic Ceilings to obtain
    4336             :                          int const TotRectIZCeilings,              // Number of Interzone Ceilings to obtain
    4337             :                          int const TotRectGCFloors,                // Number of Floors with Ground Contact to obtain
    4338             :                          int const TotRectIntFloors,               // Number of Adiabatic Walls to obtain
    4339             :                          int const TotRectIZFloors,                // Number of Interzone Floors to obtain
    4340             :                          const Array1D<SurfaceClass> &BaseSurfIDs, // ID Assignments for valid surface classes
    4341             :                          int &NeedToAddSurfaces                    // Number of surfaces to add, based on unentered IZ surfaces
    4342             :     )
    4343             :     {
    4344             : 
    4345             :         // SUBROUTINE INFORMATION:
    4346             :         //       AUTHOR         Linda Lawrie
    4347             :         //       DATE WRITTEN   December 2008
    4348             :         //       MODIFIED       na
    4349             :         //       RE-ENGINEERED  na
    4350             : 
    4351             :         // PURPOSE OF THIS SUBROUTINE:
    4352             :         // Get simple (rectangular, LLC corner specified) walls
    4353             : 
    4354             :         // Using/Aliasing
    4355             : 
    4356             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4357             :         static Array1D_string const cModuleObjects(10,
    4358             :                                                    {"Wall:Exterior",
    4359             :                                                     "Wall:Adiabatic",
    4360             :                                                     "Wall:Interzone",
    4361             :                                                     "Wall:Underground",
    4362             :                                                     "Roof",
    4363             :                                                     "Ceiling:Adiabatic",
    4364             :                                                     "Ceiling:Interzone",
    4365             :                                                     "Floor:GroundContact",
    4366             :                                                     "Floor:Adiabatic",
    4367         796 :                                                     "Floor:Interzone"});
    4368             : 
    4369             :         int Item;
    4370             :         int ItemsToGet;
    4371             :         int Loop;
    4372             :         int NumAlphas;
    4373             :         int NumNumbers;
    4374             :         int IOStat; // IO Status when calling get input subroutine
    4375             :         int Found;  // For matching base surfaces
    4376             :         bool GettingIZSurfaces;
    4377             :         int OtherSurfaceField;
    4378             :         int ExtBoundCondition;
    4379             :         int ClassItem;
    4380             :         int ZoneNum;
    4381         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    4382        8756 :         for (Item = 1; Item <= 10; ++Item) {
    4383             : 
    4384        7960 :             cCurrentModuleObject = cModuleObjects(Item);
    4385        7960 :             if (Item == 1) {
    4386         796 :                 ItemsToGet = TotRectExtWalls;
    4387         796 :                 GettingIZSurfaces = false;
    4388         796 :                 OtherSurfaceField = 0;
    4389         796 :                 ExtBoundCondition = ExternalEnvironment;
    4390         796 :                 ClassItem = 1;
    4391        7164 :             } else if (Item == 2) {
    4392         796 :                 ItemsToGet = TotRectIntWalls;
    4393         796 :                 GettingIZSurfaces = false;
    4394         796 :                 OtherSurfaceField = 0;
    4395         796 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4396         796 :                 ClassItem = 1;
    4397        6368 :             } else if (Item == 3) {
    4398         796 :                 ItemsToGet = TotRectIZWalls;
    4399         796 :                 GettingIZSurfaces = true;
    4400         796 :                 OtherSurfaceField = 5;
    4401         796 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4402         796 :                 ClassItem = 1;
    4403        5572 :             } else if (Item == 4) {
    4404         796 :                 ItemsToGet = TotRectUGWalls;
    4405         796 :                 GettingIZSurfaces = false;
    4406         796 :                 OtherSurfaceField = 0;
    4407         796 :                 ExtBoundCondition = Ground;
    4408         796 :                 ClassItem = 1;
    4409        4776 :             } else if (Item == 5) {
    4410         796 :                 ItemsToGet = TotRectRoofs;
    4411         796 :                 GettingIZSurfaces = false;
    4412         796 :                 OtherSurfaceField = 0;
    4413         796 :                 ExtBoundCondition = ExternalEnvironment;
    4414         796 :                 ClassItem = 3;
    4415        3980 :             } else if (Item == 6) {
    4416         796 :                 ItemsToGet = TotRectCeilings;
    4417         796 :                 GettingIZSurfaces = false;
    4418         796 :                 OtherSurfaceField = 0;
    4419         796 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4420         796 :                 ClassItem = 3;
    4421        3184 :             } else if (Item == 7) {
    4422         796 :                 ItemsToGet = TotRectIZCeilings;
    4423         796 :                 GettingIZSurfaces = false;
    4424         796 :                 OtherSurfaceField = 5;
    4425         796 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4426         796 :                 ClassItem = 3;
    4427        2388 :             } else if (Item == 8) {
    4428         796 :                 ItemsToGet = TotRectGCFloors;
    4429         796 :                 GettingIZSurfaces = false;
    4430         796 :                 OtherSurfaceField = 0;
    4431         796 :                 ExtBoundCondition = Ground;
    4432         796 :                 ClassItem = 2;
    4433        1592 :             } else if (Item == 9) {
    4434         796 :                 ItemsToGet = TotRectIntFloors;
    4435         796 :                 GettingIZSurfaces = false;
    4436         796 :                 OtherSurfaceField = 0;
    4437         796 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4438         796 :                 ClassItem = 2;
    4439             :             } else { // IF (Item == 10) THEN
    4440         796 :                 ItemsToGet = TotRectIZFloors;
    4441         796 :                 GettingIZSurfaces = true;
    4442         796 :                 OtherSurfaceField = 5;
    4443         796 :                 ExtBoundCondition = UnreconciledZoneSurface;
    4444         796 :                 ClassItem = 2;
    4445             :             }
    4446             : 
    4447        8079 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    4448         238 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4449             :                                                                          cCurrentModuleObject,
    4450             :                                                                          Loop,
    4451         119 :                                                                          state.dataIPShortCut->cAlphaArgs,
    4452             :                                                                          NumAlphas,
    4453         119 :                                                                          state.dataIPShortCut->rNumericArgs,
    4454             :                                                                          NumNumbers,
    4455             :                                                                          IOStat,
    4456         119 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    4457         119 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    4458         119 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    4459         119 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    4460             : 
    4461         238 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    4462         119 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    4463         119 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    4464             :                                                              cCurrentModuleObject,
    4465         119 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    4466             :                                                              ErrorsFound)) {
    4467           0 :                     continue;
    4468             :                 }
    4469             : 
    4470         119 :                 if (NumNumbers < 7) {
    4471           0 :                     ShowSevereError(state,
    4472           0 :                                     format("{}=\"{}\", Too few number of numeric args=[{}].",
    4473             :                                            cCurrentModuleObject,
    4474           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    4475             :                                            NumNumbers));
    4476           0 :                     ErrorsFound = true;
    4477             :                 }
    4478             : 
    4479         119 :                 ++SurfNum;
    4480         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    4481         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);             // Set class number
    4482             : 
    4483         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction =
    4484         119 :                     Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    4485             : 
    4486         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    4487           0 :                     ErrorsFound = true;
    4488           0 :                     ShowSevereError(state,
    4489           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    4490             :                                            cCurrentModuleObject,
    4491           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4492           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    4493           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    4494         119 :                 } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    4495           0 :                     ErrorsFound = true;
    4496           0 :                     ShowSevereError(state,
    4497           0 :                                     format("{}=\"{}\", invalid {}=\"{}\" - has Window materials.",
    4498             :                                            cCurrentModuleObject,
    4499           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4500           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    4501           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    4502           0 :                     ShowContinueError(state,
    4503           0 :                                       format("...because {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
    4504             :                 } else {
    4505         119 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    4506         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    4507         119 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    4508             :                 }
    4509         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    4510         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
    4511         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    4512             : 
    4513         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataIPShortCut->cAlphaArgs(3);
    4514         119 :                 ZoneNum = Util::FindItemInList(
    4515         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    4516             : 
    4517         119 :                 if (ZoneNum != 0) {
    4518         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
    4519             :                 } else {
    4520           0 :                     ShowSevereError(state,
    4521           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    4522             :                                            cCurrentModuleObject,
    4523           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4524           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    4525           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    4526           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    4527           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    4528           0 :                     ErrorsFound = true;
    4529             :                 }
    4530             : 
    4531         119 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    4532           0 :                     int spaceNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
    4533             : 
    4534           0 :                     if (spaceNum != 0) {
    4535           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
    4536             :                     } else {
    4537           0 :                         ShowSevereError(state,
    4538           0 :                                         format("{}=\"{}\", invalid {}=\"{}\".",
    4539             :                                                cCurrentModuleObject,
    4540           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4541           0 :                                                state.dataIPShortCut->cAlphaFieldNames(4),
    4542           0 :                                                state.dataIPShortCut->cAlphaArgs(4)));
    4543           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    4544           0 :                         ErrorsFound = true;
    4545             :                     }
    4546             :                 }
    4547             : 
    4548         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExtBoundCondition;
    4549         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
    4550         119 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    4551         119 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall &&
    4552           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    4553           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
    4554         119 :                     } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
    4555           0 :                         ErrorsFound = true;
    4556           0 :                         ShowSevereError(state,
    4557           0 :                                         format("{}=\"{}\", Construction type is \"Construction:CfactorUndergroundWall\" but invalid for this object.",
    4558             :                                                cCurrentModuleObject,
    4559           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    4560             :                     }
    4561         119 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    4562         119 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor &&
    4563           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    4564           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
    4565         119 :                     } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
    4566           0 :                         ErrorsFound = true;
    4567           0 :                         ShowSevereError(state,
    4568           0 :                                         format("{}=\"{}\", Construction type is \"Construction:FfactorGroundFloor\" but invalid for this object.",
    4569             :                                                cCurrentModuleObject,
    4570           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    4571             :                     }
    4572             :                 }
    4573         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
    4574         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
    4575         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = Constant::AutoCalculate;
    4576             : 
    4577         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
    4578          66 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
    4579          66 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = true;
    4580             : 
    4581             :                     // Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
    4582             :                     //                    if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0)
    4583             :                     //                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof =
    4584             :                     //                            state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof;
    4585             : 
    4586          53 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    4587          47 :                     if (GettingIZSurfaces) {
    4588          19 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(OtherSurfaceField);
    4589          19 :                         Found = Util::FindItemInList(
    4590          19 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    4591             :                         // see if match to zone, then it's an unentered other surface, else reconciled later
    4592          19 :                         if (Found > 0) {
    4593           1 :                             ++NeedToAddSurfaces;
    4594           1 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    4595             :                         }
    4596             :                     } else {
    4597          28 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    4598             :                     }
    4599             : 
    4600           6 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    4601             : 
    4602           6 :                     if (state.dataSurfaceGeometry->NoGroundTempObjWarning) {
    4603           1 :                         if (!state.dataEnvrn->GroundTempInputs[(int)DataEnvironment::GroundTempType::BuildingSurface]) {
    4604           0 :                             ShowWarningError(state,
    4605             :                                              "GetRectSurfaces: Surfaces with interface to Ground found but no \"Ground Temperatures\" were input.");
    4606           0 :                             ShowContinueError(state, format("Found first in surface={}", state.dataIPShortCut->cAlphaArgs(1)));
    4607           0 :                             ShowContinueError(state,
    4608           0 :                                               format("Defaults, constant throughout the year of ({:.1R}) will be used.",
    4609           0 :                                                      state.dataEnvrn->GroundTemp[(int)DataEnvironment::GroundTempType::BuildingSurface]));
    4610             :                         }
    4611           1 :                         state.dataSurfaceGeometry->NoGroundTempObjWarning = false;
    4612             :                     }
    4613             : 
    4614           0 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
    4615           0 :                     if (state.dataSurfaceGeometry->NoFCGroundTempObjWarning) {
    4616           0 :                         if (!state.dataEnvrn->GroundTempInputs[(int)DataEnvironment::GroundTempType::FCFactorMethod]) {
    4617           0 :                             ShowSevereError(state,
    4618             :                                             "GetRectSurfaces: Surfaces with interface to GroundFCfactorMethod found but no \"FC Ground "
    4619             :                                             "Temperatures\" were input.");
    4620           0 :                             ShowContinueError(state, format("Found first in surface={}", state.dataIPShortCut->cAlphaArgs(1)));
    4621           0 :                             ShowContinueError(state,
    4622             :                                               "Either add a \"Site:GroundTemperature:FCfactorMethod\" object or use a weather file with "
    4623             :                                               "Ground Temperatures.");
    4624           0 :                             ErrorsFound = true;
    4625           0 :                             state.dataSurfaceGeometry->NoFCGroundTempObjWarning = false;
    4626             :                         }
    4627             :                     }
    4628             : 
    4629             :                 } // ... End of the ExtBoundCond logical IF Block
    4630             : 
    4631         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataIPShortCut->rNumericArgs(1);
    4632         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataIPShortCut->rNumericArgs(2);
    4633         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    4634         119 :                     Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    4635         119 :                 if (!state.dataSurface->WorldCoordSystem) {
    4636          95 :                     if (ZoneNum != 0) {
    4637          95 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth +=
    4638          95 :                             state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->Zone(ZoneNum).RelNorth;
    4639             :                     }
    4640             :                 }
    4641         119 :                 if (ZoneNum != 0) {
    4642         119 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingRotationAppendixG;
    4643             :                 }
    4644             : 
    4645         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    4646         119 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4647             : 
    4648         714 :                 MakeRectangularVertices(state,
    4649             :                                         SurfNum,
    4650         119 :                                         state.dataIPShortCut->rNumericArgs(3),
    4651         119 :                                         state.dataIPShortCut->rNumericArgs(4),
    4652         119 :                                         state.dataIPShortCut->rNumericArgs(5),
    4653         119 :                                         state.dataIPShortCut->rNumericArgs(6),
    4654         119 :                                         state.dataIPShortCut->rNumericArgs(7),
    4655         119 :                                         state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem);
    4656             : 
    4657         119 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    4658           0 :                     ShowSevereError(state,
    4659           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    4660             :                                            cCurrentModuleObject,
    4661           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4662           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4663           0 :                     ErrorsFound = true;
    4664             :                 }
    4665             : 
    4666             :                 // Check wall height for the CFactor walls
    4667         198 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
    4668          79 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
    4669           0 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height -
    4670           0 :                                  state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Height) > 0.05) {
    4671           0 :                         ShowWarningError(state,
    4672           0 :                                          format("{}=\"{}\", underground Wall Height = {:.2T}",
    4673             :                                                 cCurrentModuleObject,
    4674           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4675           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height));
    4676           0 :                         ShowContinueError(state, "..which deos not match its construction height.");
    4677             :                     }
    4678             :                 }
    4679             : 
    4680             :                 // Check area and perimeter for the FFactor floors
    4681         139 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
    4682          20 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
    4683           0 :                     if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area -
    4684           0 :                                  state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Area) > 0.1) {
    4685           0 :                         ShowWarningError(state,
    4686           0 :                                          format("{}=\"{}\", underground Floor Area = {:.2T}",
    4687             :                                                 cCurrentModuleObject,
    4688           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4689           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    4690           0 :                         ShowContinueError(state, "..which does not match its construction area.");
    4691             :                     }
    4692           0 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter <
    4693           0 :                         state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).PerimeterExposed - 0.1) {
    4694           0 :                         ShowWarningError(state,
    4695           0 :                                          format("{}=\"{}\", underground Floor Perimeter = {:.2T}",
    4696             :                                                 cCurrentModuleObject,
    4697           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    4698           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter));
    4699           0 :                         ShowContinueError(state, "..which is less than its construction exposed perimeter.");
    4700             :                     }
    4701             :                 }
    4702             :             } // Getting Items
    4703             :         }
    4704         796 :     }
    4705             : 
    4706         139 :     void MakeRectangularVertices(EnergyPlusData &state,
    4707             :                                  int const SurfNum,
    4708             :                                  Real64 const XCoord,
    4709             :                                  Real64 const YCoord,
    4710             :                                  Real64 const ZCoord,
    4711             :                                  Real64 const Length,
    4712             :                                  Real64 const Height,
    4713             :                                  bool const SurfWorldCoordSystem)
    4714             :     {
    4715             : 
    4716             :         // SUBROUTINE INFORMATION:
    4717             :         //       AUTHOR         Linda Lawrie
    4718             :         //       DATE WRITTEN   December 2008
    4719             :         //       MODIFIED       na
    4720             :         //       RE-ENGINEERED  na
    4721             : 
    4722             :         // PURPOSE OF THIS SUBROUTINE:
    4723             :         // This routine creates world/3d coordinates for rectangular surfaces using azimuth, tilt, LLC (X,Y,Z), length & height.
    4724             : 
    4725             :         // METHODOLOGY EMPLOYED:
    4726             :         // na
    4727             : 
    4728             :         // REFERENCES:
    4729             :         // na
    4730             : 
    4731             :         // Using/Aliasing
    4732             :         using namespace Vectors;
    4733             : 
    4734             :         // Locals
    4735             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    4736             : 
    4737             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4738             :         // na
    4739             : 
    4740             :         // INTERFACE BLOCK SPECIFICATIONS:
    4741             :         // na
    4742             : 
    4743             :         // DERIVED TYPE DEFINITIONS:
    4744             :         // na
    4745             : 
    4746             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4747             :         Real64 SurfAzimuth; // Surface Azimuth/Facing (same as Base Surface)
    4748             :         Real64 SurfTilt;    // Tilt (same as Base Surface)
    4749             :         Real64 XLLC;
    4750             :         Real64 YLLC;
    4751             :         Real64 ZLLC;
    4752             :         Real64 CosSurfAzimuth;
    4753             :         Real64 SinSurfAzimuth;
    4754             :         Real64 CosSurfTilt;
    4755             :         Real64 SinSurfTilt;
    4756         139 :         Array1D<Real64> XX(4);
    4757         139 :         Array1D<Real64> YY(4);
    4758             :         Real64 Xb;
    4759             :         Real64 Yb;
    4760             :         Real64 Perimeter;
    4761             :         int n;
    4762             :         int Vrt;
    4763             : 
    4764         159 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone == 0 &&
    4765          20 :             (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F &&
    4766           6 :              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_B))
    4767           0 :             return;
    4768             : 
    4769         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = Height;
    4770         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = Length;
    4771             : 
    4772         139 :         SurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
    4773         139 :         SurfTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
    4774         139 :         CosSurfAzimuth = std::cos(SurfAzimuth * Constant::DegToRadians);
    4775         139 :         SinSurfAzimuth = std::sin(SurfAzimuth * Constant::DegToRadians);
    4776         139 :         CosSurfTilt = std::cos(SurfTilt * Constant::DegToRadians);
    4777         139 :         SinSurfTilt = std::sin(SurfTilt * Constant::DegToRadians);
    4778         139 :         if (!SurfWorldCoordSystem) {
    4779         111 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone > 0) {
    4780          95 :                 Xb = XCoord * state.dataSurfaceGeometry->CosZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) -
    4781          95 :                      YCoord * state.dataSurfaceGeometry->SinZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
    4782          95 :                      state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginX;
    4783          95 :                 Yb = XCoord * state.dataSurfaceGeometry->SinZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
    4784          95 :                      YCoord * state.dataSurfaceGeometry->CosZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
    4785          95 :                      state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginY;
    4786          95 :                 XLLC = Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    4787          95 :                 YLLC = Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    4788          95 :                 ZLLC = ZCoord + state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginZ;
    4789             :             } else {
    4790          16 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    4791           5 :                     Xb = XCoord;
    4792           5 :                     Yb = YCoord;
    4793           5 :                     XLLC = Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    4794           5 :                     YLLC = Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    4795           5 :                     ZLLC = ZCoord;
    4796             :                 } else {
    4797          11 :                     XLLC = XCoord;
    4798          11 :                     YLLC = YCoord;
    4799          11 :                     ZLLC = ZCoord;
    4800             :                 }
    4801             :             }
    4802             :         } else {
    4803             :             // for world coordinates, only rotate for appendix G
    4804          28 :             Xb = XCoord;
    4805          28 :             Yb = YCoord;
    4806          28 :             ZLLC = ZCoord;
    4807          28 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F) {
    4808          25 :                 XLLC = Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
    4809          25 :                 YLLC = Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
    4810             :             } else {
    4811           3 :                 XLLC = Xb;
    4812           3 :                 YLLC = Yb;
    4813             :             }
    4814             :         }
    4815             : 
    4816         139 :         XX(1) = 0.0;
    4817         139 :         XX(2) = 0.0;
    4818         139 :         XX(3) = Length;
    4819         139 :         XX(4) = Length;
    4820         139 :         YY(1) = Height;
    4821         139 :         YY(4) = Height;
    4822         139 :         YY(3) = 0.0;
    4823         139 :         YY(2) = 0.0;
    4824             : 
    4825         695 :         for (n = 1; n <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++n) {
    4826         556 :             Vrt = n;
    4827         556 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).x = XLLC - XX(n) * CosSurfAzimuth - YY(n) * CosSurfTilt * SinSurfAzimuth;
    4828         556 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).y = YLLC + XX(n) * SinSurfAzimuth - YY(n) * CosSurfTilt * CosSurfAzimuth;
    4829         556 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).z = ZLLC + YY(n) * SinSurfTilt;
    4830             :         }
    4831             : 
    4832         139 :         CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    4833         139 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4834         139 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    4835         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    4836         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    4837         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    4838         139 :         CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    4839         139 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    4840         139 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    4841         139 :         DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    4842             :                                 SurfAzimuth,
    4843             :                                 SurfTilt,
    4844         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    4845         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    4846         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    4847         139 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    4848         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfAzimuth;
    4849         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    4850         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    4851         139 :             Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    4852             :         // Sine and cosine of azimuth and tilt
    4853         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = SinSurfAzimuth;
    4854         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = CosSurfAzimuth;
    4855         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = SinSurfTilt;
    4856         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = CosSurfTilt;
    4857         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    4858             :         // Outward normal unit vector (pointing away from room)
    4859         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    4860         556 :         for (n = 1; n <= 3; ++n) {
    4861         417 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    4862          71 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    4863         417 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    4864          68 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    4865         417 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    4866         278 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    4867             :         }
    4868             : 
    4869             :         // Can perform tests on this surface here
    4870         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    4871             :         // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    4872             :         // surfaces
    4873         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    4874         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    4875             : 
    4876         139 :         Perimeter = distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides),
    4877         139 :                              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1));
    4878         556 :         for (Vrt = 2; Vrt <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vrt) {
    4879         417 :             Perimeter +=
    4880         417 :                 distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt), state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt - 1));
    4881             :         }
    4882         139 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
    4883             : 
    4884             :         // Call to transform vertices
    4885             : 
    4886         139 :         TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    4887         139 :     }
    4888             : 
    4889         796 :     void GetHTSubSurfaceData(EnergyPlusData &state,
    4890             :                              bool &ErrorsFound,                       // Error flag indicator (true if errors found)
    4891             :                              int &SurfNum,                            // Count of Current SurfaceNumber
    4892             :                              int const TotHTSubs,                     // Number of Heat Transfer SubSurfaces to obtain
    4893             :                              const Array1D_string &SubSurfCls,        // Valid Classes for Sub Surfaces
    4894             :                              const Array1D<SurfaceClass> &SubSurfIDs, // ID Assignments for valid sub surface classes
    4895             :                              int &AddedSubSurfaces,                   // Subsurfaces added when windows reference Window5
    4896             :                              int &NeedToAddSurfaces                   // Number of surfaces to add, based on unentered IZ surfaces
    4897             :     )
    4898             :     {
    4899             : 
    4900             :         // SUBROUTINE INFORMATION:
    4901             :         //       AUTHOR         Linda Lawrie
    4902             :         //       DATE WRITTEN   May 2000
    4903             :         //       MODIFIED       August 2012 - line up subsurfaces with base surface types
    4904             :         //       RE-ENGINEERED  na
    4905             : 
    4906             :         // PURPOSE OF THIS SUBROUTINE:
    4907             :         // This subroutine gets the HeatTransfer Sub Surface Data,
    4908             :         // checks it for errors, etc.
    4909             : 
    4910             :         // METHODOLOGY EMPLOYED:
    4911             :         // na
    4912             : 
    4913             :         // REFERENCES:
    4914             :         // Heat Transfer Subsurface Definition
    4915             :         // FenestrationSurface:Detailed,
    4916             :         //        \min-fields 19
    4917             :         //        \memo Used for windows, doors, glass doors, tubular daylighting devices
    4918             :         //        \format vertices
    4919             :         //   A1 , \field Name
    4920             :         //        \required-field
    4921             :         //        \type alpha
    4922             :         //   A2 , \field Surface Type
    4923             :         //        \required-field
    4924             :         //        \type choice
    4925             :         //        \key Window
    4926             :         //        \key Door
    4927             :         //        \key GlassDoor
    4928             :         //        \key TubularDaylightDome
    4929             :         //        \key TubularDaylightDiffuser
    4930             :         //   A3 , \field Construction Name
    4931             :         //        \required-field
    4932             :         //        \note To be matched with a construction in this input file
    4933             :         //        \type object-list
    4934             :         //        \object-list ConstructionNames
    4935             :         //   A4 , \field Building Surface Name
    4936             :         //        \required-field
    4937             :         //        \type object-list
    4938             :         //        \object-list SurfaceNames
    4939             :         //   A5,  \field Outside Boundary Condition Object
    4940             :         //        \type object-list
    4941             :         //        \object-list OutFaceEnvNames
    4942             :         //        \note Non-blank only if base surface field Outside Boundary Condition is
    4943             :         //        \note Surface or OtherSideCoefficients
    4944             :         //        \note If Base Surface's Surface, specify name of corresponding subsurface in adjacent zone or
    4945             :         //        \note specify current subsurface name for internal partition separating like zones
    4946             :         //        \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
    4947             :         //        \note  or leave blank to inherit Base Surface's OtherSide Coefficients
    4948             :         //   N1, \field View Factor to Ground
    4949             :         //        \type real
    4950             :         //        \note From the exterior of the surface
    4951             :         //        \note Unused if one uses the "reflections" options in Solar Distribution in Building input
    4952             :         //        \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
    4953             :         //        \note autocalculate will automatically calculate this value from the tilt of the surface
    4954             :         //        \autocalculatable
    4955             :         //        \minimum 0.0
    4956             :         //        \maximum 1.0
    4957             :         //        \default autocalculate
    4958             :         //   A6, \field Frame and Divider Name
    4959             :         //        \note Enter the name of a WindowProperty:FrameAndDivider object
    4960             :         //        \type object-list
    4961             :         //        \object-list WindowFrameAndDividerNames
    4962             :         //        \note Used only for exterior windows (rectangular) and glass doors.
    4963             :         //        \note Unused for triangular windows.
    4964             :         //        \note If not specified (blank), window or glass door has no frame or divider
    4965             :         //        \note and no beam solar reflection from reveal surfaces.
    4966             :         //   N2 , \field Multiplier
    4967             :         //        \note Used only for Surface Type = WINDOW, GLASSDOOR or DOOR
    4968             :         //        \note Non-integer values will be truncated to integer
    4969             :         //        \default 1.0
    4970             :         //        \minimum 1.0
    4971             :         //   N3 , \field Number of Vertices
    4972             :         //        \minimum 3
    4973             :         //        \maximum 4
    4974             :         //        \autocalculatable
    4975             :         //        \default autocalculate
    4976             :         //        \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
    4977             :         //        \note are "relative" to the Zone Origin.  If world, then building and zone origins are used
    4978             :         //        \note for some internal calculations, but all coordinates are given in an "absolute" system.
    4979             :         //  N4-15 as indicated by the N3 value
    4980             : 
    4981             :         // Using/Aliasing
    4982             : 
    4983             :         // Locals
    4984             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    4985             :         //  data file entry with two glazing systems
    4986             : 
    4987             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4988             :         int IOStat;          // IO Status when calling get input subroutine
    4989             :         int SurfaceNumAlpha; // Number of material alpha names being passed
    4990             :         int SurfaceNumProp;  // Number of material properties being passed
    4991             :         int Found;           // For matching interzone surfaces
    4992             :         int Loop;
    4993             :         int ValidChk;
    4994             :         int numSides;
    4995             : 
    4996         796 :         GetWindowShadingControlData(state, ErrorsFound);
    4997         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    4998         796 :         cCurrentModuleObject = "FenestrationSurface:Detailed";
    4999         796 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, SurfaceNumAlpha, SurfaceNumProp);
    5000             : 
    5001         796 :         if (SurfaceNumAlpha != 6) {
    5002           0 :             ShowSevereError(
    5003           0 :                 state, format("{}: Object Definition indicates not = 6 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    5004           0 :             ErrorsFound = true;
    5005             :         }
    5006             : 
    5007         796 :         if (SurfaceNumProp != 15) {
    5008           0 :             ShowSevereError(
    5009           0 :                 state, format("{}: Object Definition indicates > 15 Numeric Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
    5010           0 :             ErrorsFound = true;
    5011             :         }
    5012         796 :         NeedToAddSurfaces = 0;
    5013             : 
    5014        7416 :         for (Loop = 1; Loop <= TotHTSubs; ++Loop) {
    5015       13240 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5016             :                                                                      cCurrentModuleObject,
    5017             :                                                                      Loop,
    5018        6620 :                                                                      state.dataIPShortCut->cAlphaArgs,
    5019             :                                                                      SurfaceNumAlpha,
    5020        6620 :                                                                      state.dataIPShortCut->rNumericArgs,
    5021             :                                                                      SurfaceNumProp,
    5022             :                                                                      IOStat,
    5023        6620 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    5024        6620 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    5025        6620 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    5026        6620 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    5027             : 
    5028       13240 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    5029        6620 :                                                          state.dataSurfaceGeometry->UniqueSurfaceNames,
    5030        6620 :                                                          state.dataIPShortCut->cAlphaArgs(1),
    5031             :                                                          cCurrentModuleObject,
    5032        6620 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    5033             :                                                          ErrorsFound)) {
    5034           0 :                 continue;
    5035             :             }
    5036             : 
    5037        6620 :             if (SurfaceNumProp < 12) {
    5038           0 :                 ShowSevereError(state,
    5039           0 :                                 format("{}=\"{}\", Too few number of numeric args=[{}].",
    5040             :                                        cCurrentModuleObject,
    5041           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5042             :                                        SurfaceNumProp));
    5043           0 :                 ErrorsFound = true;
    5044             :             }
    5045             : 
    5046        6620 :             ++SurfNum;
    5047        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    5048        6620 :             ValidChk = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), SubSurfCls, 6);
    5049        6620 :             if (ValidChk == 0) {
    5050           0 :                 ShowSevereError(state,
    5051           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    5052             :                                        cCurrentModuleObject,
    5053           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5054           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    5055           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    5056           0 :                 ErrorsFound = true;
    5057             :             } else {
    5058        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SubSurfIDs(ValidChk); // Set class number
    5059             :             }
    5060             : 
    5061        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction =
    5062        6620 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    5063             : 
    5064        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    5065           0 :                 ShowSevereError(state,
    5066           0 :                                 format("{}=\"{}\", invalid {}=\"{}\".",
    5067             :                                        cCurrentModuleObject,
    5068           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5069           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    5070           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
    5071           0 :                 ErrorsFound = true;
    5072           0 :                 continue;
    5073             :             } else {
    5074        6620 :                 state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    5075        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    5076        6620 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    5077             :             }
    5078             : 
    5079        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5080        1008 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5081        8098 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser ||
    5082         470 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome) {
    5083             : 
    5084        6152 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5085        6152 :                     auto &construction = state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction);
    5086        6152 :                     if (!construction.TypeIsWindow && !construction.TypeIsAirBoundary) {
    5087           0 :                         ErrorsFound = true;
    5088           0 :                         ShowSevereError(state,
    5089           0 :                                         format("{}=\"{}\" has an opaque surface construction; it should have a window construction.",
    5090             :                                                cCurrentModuleObject,
    5091           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5092             :                     }
    5093        6152 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
    5094           0 :                         ErrorsFound = true;
    5095           0 :                         ShowSevereError(state,
    5096           0 :                                         format("{}=\"{}\": Windows are not allowed to have embedded sources/sinks",
    5097             :                                                cCurrentModuleObject,
    5098           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5099             :                     }
    5100             :                 }
    5101             : 
    5102         468 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5103         468 :                 if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    5104           0 :                     ErrorsFound = true;
    5105           0 :                     ShowSevereError(state,
    5106           0 :                                     format("{}=\"{}\", invalid {}=\"{}\" - has Window materials.",
    5107             :                                            cCurrentModuleObject,
    5108           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5109           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    5110           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    5111           0 :                     ShowContinueError(state,
    5112           0 :                                       format("...because {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
    5113             :                 }
    5114             :             }
    5115             : 
    5116        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    5117             : 
    5118        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(4);
    5119             :             //  The subsurface inherits properties from the base surface
    5120             :             //  Exterior conditions, Zone, etc.
    5121             :             //  We can figure out the base surface though, because they've all been entered
    5122        6620 :             Found = Util::FindItemInList(
    5123        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
    5124        6620 :             if (Found > 0) {
    5125        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
    5126        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    5127        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName;
    5128        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    5129        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    5130        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
    5131        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
    5132        6620 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
    5133        6684 :                 if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface &&
    5134          64 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName ==
    5135          64 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed
    5136           0 :                     ShowSevereError(state,
    5137           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    5138             :                                            cCurrentModuleObject,
    5139           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5140           0 :                                            state.dataIPShortCut->cAlphaFieldNames(4),
    5141           0 :                                            state.dataIPShortCut->cAlphaArgs(4)));
    5142           0 :                     ShowContinueError(state, "... adiabatic surfaces cannot have windows or doors.");
    5143           0 :                     ShowContinueError(state,
    5144             :                                       "... no solar transmission will result for these windows or doors. You must have interior windows or doors on "
    5145             :                                       "Interzone surfaces for transmission to result.");
    5146             :                 }
    5147             :             } else {
    5148           0 :                 ShowSevereError(state,
    5149           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    5150             :                                        cCurrentModuleObject,
    5151           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5152           0 :                                        state.dataIPShortCut->cAlphaFieldNames(4),
    5153           0 :                                        state.dataIPShortCut->cAlphaArgs(4)));
    5154           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    5155           0 :                 ErrorsFound = true;
    5156             :             }
    5157       13238 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome ||
    5158        6618 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser) {
    5159           4 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    5160             :             }
    5161             : 
    5162        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
    5163        6541 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    5164           0 :                     ShowWarningError(state,
    5165           0 :                                      format("{}=\"{}\", invalid field {}",
    5166             :                                             cCurrentModuleObject,
    5167           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5168           0 :                                             state.dataIPShortCut->cAlphaFieldNames(5)));
    5169           0 :                     ShowContinueError(
    5170             :                         state,
    5171           0 :                         format("...when Base surface uses \"Outdoors\" as {}, subsurfaces need to be blank to inherit the outdoor characteristics.",
    5172           0 :                                state.dataIPShortCut->cAlphaFieldNames(5)));
    5173           0 :                     ShowContinueError(state, "...Surface external characteristics changed to reflect base surface.");
    5174             :                 }
    5175             :             }
    5176             : 
    5177        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
    5178          62 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    5179          62 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(5);
    5180             :                 } else {
    5181           0 :                     ShowSevereError(state,
    5182           0 :                                     format("{}=\"{}\", invalid blank {}",
    5183             :                                            cCurrentModuleObject,
    5184           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5185           0 :                                            state.dataIPShortCut->cAlphaFieldNames(5)));
    5186           0 :                     ShowContinueError(
    5187             :                         state,
    5188           0 :                         format("...when Base surface uses \"Surface\" as {}, subsurfaces must also specify specific surfaces in the adjacent zone.",
    5189           0 :                                state.dataIPShortCut->cAlphaFieldNames(5)));
    5190           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5191           0 :                         state.dataIPShortCut->cAlphaArgs(5); // putting it as blank will not confuse things later.
    5192           0 :                     ErrorsFound = true;
    5193             :                 }
    5194             :             }
    5195             : 
    5196        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface
    5197           1 :                 ++NeedToAddSurfaces;
    5198             :                 // ignoring window5datafiles for now -- will need to add.
    5199             :             }
    5200             : 
    5201       13224 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
    5202        6604 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
    5203          16 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { // Otherside Coef special Name
    5204           2 :                     Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(5), state.dataSurface->OSC, state.dataSurface->TotOSC);
    5205           2 :                     if (Found == 0) {
    5206           0 :                         ShowSevereError(state,
    5207           0 :                                         format("{}=\"{}\", invalid {}=\"{}\".",
    5208             :                                                cCurrentModuleObject,
    5209           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5210           0 :                                                state.dataIPShortCut->cAlphaFieldNames(5),
    5211           0 :                                                state.dataIPShortCut->cAlphaArgs(5)));
    5212           0 :                         ShowContinueError(state, "...base surface requires that this subsurface have OtherSideCoefficients -- not found.");
    5213           0 :                         ErrorsFound = true;
    5214             :                     } else { // found
    5215             :                         // The following allows for a subsurface that has different characteristics than
    5216             :                         // the base surface with OtherSide Coeff -- do we want that or is it an error?
    5217           2 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
    5218           2 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(5);
    5219           2 :                         if (state.dataSurface->OSC(Found).SurfFilmCoef > 0.0) {
    5220           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefCalcExt;
    5221             :                         } else {
    5222           2 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefNoCalcExt;
    5223             :                         }
    5224             :                     }
    5225             :                 }
    5226             :             }
    5227             : 
    5228        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCondModeledExt) {
    5229           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    5230             :             }
    5231             : 
    5232        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName == BlankString) {
    5233        6531 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    5234             :             }
    5235        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataIPShortCut->rNumericArgs(1);
    5236        6620 :             if (state.dataIPShortCut->lNumericFieldBlanks(1))
    5237         399 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = Constant::AutoCalculate;
    5238             : 
    5239        6620 :             if (state.dataIPShortCut->lNumericFieldBlanks(3) || state.dataIPShortCut->rNumericArgs(3) == Constant::AutoCalculate) {
    5240          97 :                 state.dataIPShortCut->rNumericArgs(3) = (SurfaceNumProp - 3) / 3;
    5241          97 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(3);
    5242          97 :                 if (mod(SurfaceNumProp - 3, 3) != 0) {
    5243           0 :                     ShowWarningError(state,
    5244           0 :                                      format("{}=\"{}\", {}",
    5245             :                                             cCurrentModuleObject,
    5246           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5247           0 :                                             format("{} not even multiple of 3. Will read in {}",
    5248           0 :                                                    state.dataIPShortCut->cNumericFieldNames(3),
    5249           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    5250             :                 }
    5251          97 :                 if (state.dataIPShortCut->rNumericArgs(3) < 3) {
    5252           0 :                     ShowSevereError(state,
    5253           0 :                                     format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    5254             :                                            cCurrentModuleObject,
    5255           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5256           0 :                                            state.dataIPShortCut->cNumericFieldNames(3),
    5257           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    5258           0 :                     ErrorsFound = true;
    5259           0 :                     continue;
    5260             :                 }
    5261             :             } else {
    5262        6523 :                 numSides = (SurfaceNumProp - 2) / 3;
    5263        6523 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(3);
    5264        6523 :                 if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
    5265           0 :                     ShowWarningError(state,
    5266           0 :                                      format("{}=\"{}\", field {}={}",
    5267             :                                             cCurrentModuleObject,
    5268           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5269           0 :                                             state.dataIPShortCut->cNumericFieldNames(3),
    5270           0 :                                             fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    5271           0 :                     ShowContinueError(
    5272             :                         state,
    5273           0 :                         format("...but {} were entered. Only the indicated {} will be used.", numSides, state.dataIPShortCut->cNumericFieldNames(3)));
    5274             :                 }
    5275             :             }
    5276        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    5277        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5278        7092 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5279         472 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    5280        6616 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = int(state.dataIPShortCut->rNumericArgs(2));
    5281             :             // Only windows, glass doors and doors can have Multiplier > 1:
    5282        6620 :             if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
    5283        1008 :                  state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
    5284        7632 :                  state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door) &&
    5285           4 :                 state.dataIPShortCut->rNumericArgs(2) > 1.0) {
    5286           0 :                 ShowWarningError(state,
    5287           0 :                                  format("{}=\"{}\", invalid {}=[{:.1T}].",
    5288             :                                         cCurrentModuleObject,
    5289           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5290           0 :                                         state.dataIPShortCut->cNumericFieldNames(2),
    5291           0 :                                         state.dataIPShortCut->rNumericArgs(2)));
    5292           0 :                 ShowContinueError(state,
    5293           0 :                                   format("...because {}={} multiplier will be set to 1.0.",
    5294           0 :                                          state.dataIPShortCut->cAlphaFieldNames(2),
    5295           0 :                                          state.dataIPShortCut->cAlphaArgs(2)));
    5296           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = 1.0;
    5297             :             }
    5298             : 
    5299       19860 :             GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({4, _}));
    5300             : 
    5301        6620 :             CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    5302        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.clear();
    5303        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
    5304        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = false;
    5305             : 
    5306        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.clear();
    5307        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = 0;
    5308        6620 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList.clear();
    5309             : 
    5310        6620 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5311        1008 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5312        8098 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser ||
    5313         470 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome) {
    5314             : 
    5315       12304 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
    5316        6152 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
    5317           0 :                     ShowSevereError(state,
    5318           0 :                                     format("{}=\"{}\", Other side coefficients are not allowed with windows.",
    5319             :                                            cCurrentModuleObject,
    5320           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5321           0 :                     ErrorsFound = true;
    5322             :                 }
    5323             : 
    5324        6152 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    5325           0 :                     ShowSevereError(state,
    5326           0 :                                     format("{}=\"{}\", Exterior boundary condition = Ground is not allowed with windows.",
    5327             :                                            cCurrentModuleObject,
    5328           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5329           0 :                     ErrorsFound = true;
    5330             :                 }
    5331             : 
    5332        6152 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == KivaFoundation) {
    5333           0 :                     ShowSevereError(state,
    5334           0 :                                     format("{}=\"{}\", Exterior boundary condition = Foundation is not allowed with windows.",
    5335             :                                            cCurrentModuleObject,
    5336           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5337           0 :                     ErrorsFound = true;
    5338             :                 }
    5339             : 
    5340        6152 :                 InitialAssociateWindowShadingControlFenestration(state, ErrorsFound, SurfNum);
    5341             : 
    5342        6152 :                 CheckWindowShadingControlFrameDivider(state, "GetHTSubSurfaceData", ErrorsFound, SurfNum, 6);
    5343             : 
    5344        6152 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides == 3) { // Triangular window
    5345           2 :                     if (!state.dataIPShortCut->cAlphaArgs(6).empty()) {
    5346           0 :                         ShowWarningError(state,
    5347           0 :                                          format("{}=\"{}\", invalid {}=\"{}\".",
    5348             :                                                 cCurrentModuleObject,
    5349           0 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5350           0 :                                                 state.dataIPShortCut->cAlphaFieldNames(6),
    5351           0 :                                                 state.dataIPShortCut->cAlphaArgs(6)));
    5352           0 :                         ShowContinueError(state, ".. because it is a triangular window and cannot have a frame or divider or reveal reflection.");
    5353           0 :                         ShowContinueError(state, "Frame, divider and reveal reflection will be ignored for this window.");
    5354             :                     }
    5355           2 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider = 0;
    5356             :                 } // End of check if window is triangular or rectangular
    5357             : 
    5358             :             } // check on non-opaquedoor subsurfaces
    5359             : 
    5360        6620 :             CheckSubSurfaceMiscellaneous(state,
    5361             :                                          "GetHTSubSurfaceData",
    5362             :                                          ErrorsFound,
    5363             :                                          SurfNum,
    5364        6620 :                                          state.dataIPShortCut->cAlphaArgs(1),
    5365        6620 :                                          state.dataIPShortCut->cAlphaArgs(3),
    5366             :                                          AddedSubSurfaces);
    5367             : 
    5368             :         } // End of main loop over subsurfaces
    5369         796 :     }
    5370             : 
    5371         796 :     void GetRectSubSurfaces(EnergyPlusData &state,
    5372             :                             bool &ErrorsFound,                       // Error flag indicator (true if errors found)
    5373             :                             int &SurfNum,                            // Count of Current SurfaceNumber
    5374             :                             int const TotWindows,                    // Number of Window SubSurfaces to obtain
    5375             :                             int const TotDoors,                      // Number of Door SubSurfaces to obtain
    5376             :                             int const TotGlazedDoors,                // Number of Glass Door SubSurfaces to obtain
    5377             :                             int const TotIZWindows,                  // Number of Interzone Window SubSurfaces to obtain
    5378             :                             int const TotIZDoors,                    // Number of Interzone Door SubSurfaces to obtain
    5379             :                             int const TotIZGlazedDoors,              // Number of Interzone Glass Door SubSurfaces to obtain
    5380             :                             const Array1D<SurfaceClass> &SubSurfIDs, // ID Assignments for valid sub surface classes
    5381             :                             int &AddedSubSurfaces,                   // Subsurfaces added when windows reference Window5
    5382             :                             int &NeedToAddSubSurfaces                // Number of surfaces to add, based on unentered IZ surfaces
    5383             :     )
    5384             :     {
    5385             : 
    5386             :         // SUBROUTINE INFORMATION:
    5387             :         //       AUTHOR         Linda Lawrie
    5388             :         //       DATE WRITTEN   December 2008
    5389             :         //       MODIFIED       na
    5390             :         //       RE-ENGINEERED  na
    5391             : 
    5392             :         // PURPOSE OF THIS SUBROUTINE:
    5393             :         // Get simple (rectangular, relative origin to base surface) windows, doors, glazed doors.
    5394             : 
    5395             :         // Using/Aliasing
    5396             : 
    5397             :         // Locals
    5398             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    5399             :         //  data file entry with two glazing systems
    5400             : 
    5401             :         // SUBROUTINE PARAMETER DEFINITIONS:
    5402         796 :         static Array1D_string const cModuleObjects(6, {"Window", "Door", "GlazedDoor", "Window:Interzone", "Door:Interzone", "GlazedDoor:Interzone"});
    5403             : 
    5404             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5405             :         int Item;
    5406             :         int ItemsToGet;
    5407             :         int Loop;
    5408             :         int NumAlphas;
    5409             :         int NumNumbers;
    5410             :         int IOStat; // IO Status when calling get input subroutine
    5411             :         int Found;  // For matching base surfaces
    5412             :         bool GettingIZSurfaces;
    5413             :         int WindowShadingField;
    5414             :         int FrameField;
    5415             :         int OtherSurfaceField;
    5416             :         int ClassItem;
    5417             :         int IZFound;
    5418         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    5419        5572 :         for (Item = 1; Item <= 6; ++Item) {
    5420             : 
    5421        4776 :             cCurrentModuleObject = cModuleObjects(Item);
    5422        4776 :             if (Item == 1) {
    5423         796 :                 ItemsToGet = TotWindows;
    5424         796 :                 GettingIZSurfaces = false;
    5425         796 :                 WindowShadingField = 4;
    5426         796 :                 FrameField = 5;
    5427         796 :                 OtherSurfaceField = 0;
    5428         796 :                 ClassItem = 1;
    5429        3980 :             } else if (Item == 2) {
    5430         796 :                 ItemsToGet = TotDoors;
    5431         796 :                 GettingIZSurfaces = false;
    5432         796 :                 WindowShadingField = 0;
    5433         796 :                 FrameField = 0;
    5434         796 :                 OtherSurfaceField = 0;
    5435         796 :                 ClassItem = 2;
    5436        3184 :             } else if (Item == 3) {
    5437         796 :                 ItemsToGet = TotGlazedDoors;
    5438         796 :                 GettingIZSurfaces = false;
    5439         796 :                 WindowShadingField = 4;
    5440         796 :                 FrameField = 5;
    5441         796 :                 OtherSurfaceField = 0;
    5442         796 :                 ClassItem = 3;
    5443        2388 :             } else if (Item == 4) {
    5444         796 :                 ItemsToGet = TotIZWindows;
    5445         796 :                 GettingIZSurfaces = true;
    5446         796 :                 WindowShadingField = 0;
    5447         796 :                 FrameField = 0;
    5448         796 :                 OtherSurfaceField = 4;
    5449         796 :                 ClassItem = 1;
    5450        1592 :             } else if (Item == 5) {
    5451         796 :                 ItemsToGet = TotIZDoors;
    5452         796 :                 GettingIZSurfaces = true;
    5453         796 :                 WindowShadingField = 0;
    5454         796 :                 FrameField = 0;
    5455         796 :                 OtherSurfaceField = 4;
    5456         796 :                 ClassItem = 2;
    5457             :             } else { // Item = 6
    5458         796 :                 ItemsToGet = TotIZGlazedDoors;
    5459         796 :                 GettingIZSurfaces = true;
    5460         796 :                 WindowShadingField = 0;
    5461         796 :                 FrameField = 0;
    5462         796 :                 OtherSurfaceField = 4;
    5463         796 :                 ClassItem = 3;
    5464             :             }
    5465             : 
    5466        4850 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    5467         148 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5468             :                                                                          cCurrentModuleObject,
    5469             :                                                                          Loop,
    5470          74 :                                                                          state.dataIPShortCut->cAlphaArgs,
    5471             :                                                                          NumAlphas,
    5472          74 :                                                                          state.dataIPShortCut->rNumericArgs,
    5473             :                                                                          NumNumbers,
    5474             :                                                                          IOStat,
    5475          74 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    5476          74 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    5477          74 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    5478          74 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    5479             : 
    5480         148 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    5481          74 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    5482          74 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    5483             :                                                              cCurrentModuleObject,
    5484          74 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    5485             :                                                              ErrorsFound)) {
    5486           0 :                     continue;
    5487             :                 }
    5488             : 
    5489          74 :                 if (NumNumbers < 5) {
    5490           0 :                     ShowSevereError(state,
    5491           0 :                                     format("{}=\"{}\", Too few number of numeric args=[{}].",
    5492             :                                            cCurrentModuleObject,
    5493           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    5494             :                                            NumNumbers));
    5495           0 :                     ErrorsFound = true;
    5496             :                 }
    5497             : 
    5498          74 :                 ++SurfNum;
    5499          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    5500          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SubSurfIDs(ClassItem);              // Set class number
    5501             : 
    5502          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction =
    5503          74 :                     Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    5504             : 
    5505          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
    5506           0 :                     ErrorsFound = true;
    5507           0 :                     ShowSevereError(state,
    5508           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    5509             :                                            cCurrentModuleObject,
    5510           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5511           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    5512           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    5513             :                 } else {
    5514          74 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
    5515          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    5516          74 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    5517             :                 }
    5518             : 
    5519          85 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5520          11 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) {
    5521             : 
    5522          65 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5523          65 :                         auto &construction = state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction);
    5524          65 :                         if (!construction.TypeIsWindow && !construction.TypeIsAirBoundary) {
    5525           0 :                             ErrorsFound = true;
    5526           0 :                             ShowSevereError(state,
    5527           0 :                                             format("{}=\"{}\" has an opaque surface construction; it should have a window construction.",
    5528             :                                                    cCurrentModuleObject,
    5529           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5530             :                         }
    5531          65 :                         if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
    5532           0 :                             ErrorsFound = true;
    5533           0 :                             ShowSevereError(state,
    5534           0 :                                             format("{}=\"{}\": Windows are not allowed to have embedded sources/sinks",
    5535             :                                                    cCurrentModuleObject,
    5536           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5537             :                         }
    5538             :                     }
    5539             : 
    5540           9 :                 } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    5541           9 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
    5542           0 :                         ErrorsFound = true;
    5543           0 :                         ShowSevereError(state,
    5544           0 :                                         format("{}=\"{}\", invalid {}=\"{}\" - has Window materials.",
    5545             :                                                cCurrentModuleObject,
    5546           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5547           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    5548           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
    5549             :                     }
    5550             :                 }
    5551             : 
    5552          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    5553             : 
    5554          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(3);
    5555             :                 //  The subsurface inherits properties from the base surface
    5556             :                 //  Exterior conditions, Zone, etc.
    5557             :                 //  We can figure out the base surface though, because they've all been entered
    5558          74 :                 Found = Util::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
    5559          74 :                                              state.dataSurfaceGeometry->SurfaceTmp,
    5560          74 :                                              state.dataSurface->TotSurfaces);
    5561          74 :                 if (Found > 0) {
    5562          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
    5563          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    5564          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName;
    5565          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    5566          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    5567          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
    5568          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    5569          74 :                         Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    5570          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth;
    5571          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
    5572          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
    5573          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
    5574          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataSurfaceGeometry->SurfaceTmp(Found).ViewFactorGround;
    5575          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = state.dataSurfaceGeometry->SurfaceTmp(Found).ViewFactorSky;
    5576             :                 } else {
    5577           0 :                     ShowSevereError(state,
    5578           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    5579             :                                            cCurrentModuleObject,
    5580           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5581           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    5582           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    5583           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    5584           0 :                     ErrorsFound = true;
    5585           0 :                     continue;
    5586             :                 }
    5587          82 :                 if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface &&
    5588           8 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName ==
    5589           8 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed
    5590           0 :                     ShowSevereError(state,
    5591           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    5592             :                                            cCurrentModuleObject,
    5593           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5594           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    5595           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    5596           0 :                     ShowContinueError(state, "... adiabatic surfaces cannot have windows or doors.");
    5597           0 :                     ShowContinueError(state,
    5598             :                                       "... no solar transmission will result for these windows or doors. You must have interior windows or doors on "
    5599             :                                       "Interzone surfaces for transmission to result.");
    5600             :                 }
    5601             : 
    5602          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
    5603           8 :                     if (!GettingIZSurfaces) {
    5604           0 :                         ShowSevereError(
    5605             :                             state,
    5606           0 :                             format("{}=\"{}\", invalid use of object", cCurrentModuleObject, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5607           0 :                         ShowContinueError(
    5608             :                             state,
    5609           0 :                             format(
    5610             :                                 "...when Base surface uses \"Surface\" as {}, subsurfaces must also specify specific surfaces in the adjacent zone.",
    5611           0 :                                 state.dataIPShortCut->cAlphaFieldNames(5)));
    5612           0 :                         ShowContinueError(state, format("...Please use {}:Interzone to enter this surface.", cCurrentModuleObject));
    5613           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5614           0 :                             BlankString; // putting it as blank will not confuse things later.
    5615           0 :                         ErrorsFound = true;
    5616             :                     }
    5617             :                 }
    5618             : 
    5619          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
    5620           8 :                     if (GettingIZSurfaces) {
    5621           8 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(OtherSurfaceField);
    5622           8 :                         IZFound = Util::FindItemInList(
    5623           8 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    5624           8 :                         if (IZFound > 0) state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    5625             :                     } else { // Interior Window
    5626           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    5627             :                     }
    5628             :                 }
    5629             : 
    5630             :                 // This is the parent's property:
    5631          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond ==
    5632             :                     UnenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface
    5633           3 :                     if (GettingIZSurfaces) {
    5634           3 :                         ++NeedToAddSubSurfaces;
    5635             :                     } else { // Interior Window
    5636           0 :                         ShowSevereError(state,
    5637           0 :                                         format("{}=\"{}\", invalid Interzone Surface, specify {}:InterZone",
    5638             :                                                cCurrentModuleObject,
    5639           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5640             :                                                cCurrentModuleObject));
    5641           0 :                         ShowContinueError(state, "...when base surface is an interzone surface, subsurface must also be an interzone surface.");
    5642           0 :                         ++NeedToAddSubSurfaces;
    5643           0 :                         ErrorsFound = true;
    5644             :                     }
    5645             :                 }
    5646             : 
    5647          74 :                 if (GettingIZSurfaces) {
    5648          11 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(OtherSurfaceField)) {
    5649             :                         // blank -- set it up for unentered adjacent zone
    5650           0 :                         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond ==
    5651             :                             UnenteredAdjacentZoneSurface) { // already set but need Zone
    5652           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5653           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName; // base surface has it
    5654           0 :                         } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    5655           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
    5656           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // base surface has it
    5657           0 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
    5658             :                         } else { // not correct boundary condition for interzone subsurface
    5659           0 :                             ShowSevereError(state,
    5660           0 :                                             format("{}=\"{}\", invalid Base Surface type for Interzone Surface",
    5661             :                                                    cCurrentModuleObject,
    5662           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5663           0 :                             ShowContinueError(state,
    5664             :                                               "...when base surface is not an interzone surface, subsurface must also not be an interzone surface.");
    5665           0 :                             ErrorsFound = true;
    5666             :                         }
    5667             :                     }
    5668             :                 }
    5669             : 
    5670          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCondModeledExt) {
    5671           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
    5672             :                 }
    5673             : 
    5674             :                 //      SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate
    5675             : 
    5676          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    5677          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    5678          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5679          83 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    5680           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    5681          74 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = int(state.dataIPShortCut->rNumericArgs(1));
    5682             :                 // Only windows, glass doors and doors can have Multiplier > 1:
    5683          74 :                 if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
    5684          11 :                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
    5685          85 :                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door) &&
    5686           0 :                     state.dataIPShortCut->rNumericArgs(1) > 1.0) {
    5687           0 :                     ShowWarningError(state,
    5688           0 :                                      format("{}=\"{}\", invalid {}=[{:.1T}].",
    5689             :                                             cCurrentModuleObject,
    5690           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5691           0 :                                             state.dataIPShortCut->cNumericFieldNames(1),
    5692           0 :                                             state.dataIPShortCut->rNumericArgs(1)));
    5693           0 :                     ShowContinueError(state,
    5694           0 :                                       format("...because {}={} multiplier will be set to 1.0.",
    5695           0 :                                              state.dataIPShortCut->cAlphaFieldNames(1),
    5696           0 :                                              state.dataIPShortCut->cAlphaArgs(1)));
    5697           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = 1.0;
    5698             :                 }
    5699             : 
    5700         370 :                 MakeRelativeRectangularVertices(state,
    5701          74 :                                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf,
    5702             :                                                 SurfNum,
    5703          74 :                                                 state.dataIPShortCut->rNumericArgs(2),
    5704          74 :                                                 state.dataIPShortCut->rNumericArgs(3),
    5705          74 :                                                 state.dataIPShortCut->rNumericArgs(4),
    5706          74 :                                                 state.dataIPShortCut->rNumericArgs(5));
    5707             : 
    5708          74 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
    5709           0 :                     ShowSevereError(state,
    5710           0 :                                     format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
    5711             :                                            cCurrentModuleObject,
    5712           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    5713           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
    5714           0 :                     ErrorsFound = true;
    5715             :                 }
    5716             : 
    5717          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.clear();
    5718          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
    5719          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = false;
    5720             : 
    5721          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.clear();
    5722          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = 0;
    5723          74 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList.clear();
    5724             : 
    5725          74 :                 InitialAssociateWindowShadingControlFenestration(state, ErrorsFound, SurfNum);
    5726             : 
    5727          83 :                 if (!GettingIZSurfaces && (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    5728           9 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor)) {
    5729             : 
    5730         110 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
    5731          55 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
    5732           0 :                         ShowSevereError(state,
    5733           0 :                                         format("{}=\"{}\", Other side coefficients are not allowed with windows.",
    5734             :                                                cCurrentModuleObject,
    5735           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5736           0 :                         ErrorsFound = true;
    5737             :                     }
    5738             : 
    5739          55 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
    5740           0 :                         ShowSevereError(state,
    5741           0 :                                         format("{}=\"{}\", Exterior boundary condition = Ground is not allowed with windows.",
    5742             :                                                cCurrentModuleObject,
    5743           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5744           0 :                         ErrorsFound = true;
    5745             :                     }
    5746             : 
    5747          55 :                     CheckWindowShadingControlFrameDivider(state, "GetRectSubSurfaces", ErrorsFound, SurfNum, FrameField);
    5748             : 
    5749             :                 } // check on non-opaquedoor subsurfaces
    5750             : 
    5751          74 :                 CheckSubSurfaceMiscellaneous(state,
    5752             :                                              "GetRectSubSurfaces",
    5753             :                                              ErrorsFound,
    5754             :                                              SurfNum,
    5755          74 :                                              state.dataIPShortCut->cAlphaArgs(1),
    5756          74 :                                              state.dataIPShortCut->cAlphaArgs(2),
    5757             :                                              AddedSubSurfaces);
    5758             : 
    5759             :             } // Getting Items
    5760             :         }
    5761         796 :     }
    5762             : 
    5763        6207 :     void CheckWindowShadingControlFrameDivider(EnergyPlusData &state,
    5764             :                                                std::string_view const cRoutineName, // routine name calling this one (for error messages)
    5765             :                                                bool &ErrorsFound,                   // true if errors have been found or are found here
    5766             :                                                int const SurfNum,                   // current surface number
    5767             :                                                int const FrameField                 // field number for frame/divider
    5768             :     )
    5769             :     {
    5770             : 
    5771             :         // SUBROUTINE INFORMATION:
    5772             :         //       AUTHOR         Linda Lawrie
    5773             :         //       DATE WRITTEN   December 2008
    5774             :         //       MODIFIED       na
    5775             :         //       RE-ENGINEERED  na
    5776             : 
    5777             :         // PURPOSE OF THIS SUBROUTINE:
    5778             :         // This routine performs checks on WindowShadingControl settings and Frame/Divider Settings.
    5779             : 
    5780             :         // Using/Aliasing
    5781             : 
    5782             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5783             :         int ConstrNumSh;    // Construction number with Shade
    5784             :         int ConstrNum;      // Construction number
    5785             :         int ShDevNum;       // Shading Device number
    5786             :         int Lay;            // Layer number
    5787             :         int TotGlassLayers; // Number of glass layers in window construction
    5788             :         int TotLayers;      // Number of layers in unshaded construction
    5789             :         int TotShLayers;    // Number of layers in shaded construction
    5790             :         int MatGap;         // Gap material number
    5791             :         int MatGap1;        // Material number of gap to left (outer side) of between-glass shade/blind
    5792             :         int MatGap2;        // Material number of gap to right (inner side) of between-glass shade/blind
    5793             :         int MatSh;          // Between-glass shade/blind material number
    5794             :         Real64 MatGapCalc;  // Calculated MatGap diff for shaded vs non-shaded constructions
    5795             : 
    5796             :         // If WindowShadingControl has been specified for this window --
    5797             :         // Set shaded construction number if shaded construction was specified in WindowShadingControl.
    5798             :         // Otherwise, create shaded construction if WindowShadingControl for this window has
    5799             :         // interior or exterior shade/blind (but not between-glass shade/blind) specified.
    5800             : 
    5801        6362 :         for (std::size_t shadeControlIndex = 0; shadeControlIndex < state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.size();
    5802             :              ++shadeControlIndex) {
    5803         155 :             int WSCPtr = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList[shadeControlIndex];
    5804         155 :             ConstrNumSh = 0;
    5805         155 :             if (!ErrorsFound && state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl) {
    5806         155 :                 ConstrNumSh = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex];
    5807         155 :                 if (ConstrNumSh > 0) {
    5808         137 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNumSh;
    5809             :                 } else {
    5810          18 :                     if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType) ||
    5811           0 :                         ANY_EXTERIOR_SHADE_BLIND_SCREEN(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5812          18 :                         ShDevNum = state.dataSurface->WindowShadingControl(WSCPtr).ShadingDevice;
    5813          18 :                         if (ShDevNum > 0) {
    5814          18 :                             CreateShadedWindowConstruction(state, SurfNum, WSCPtr, ShDevNum, shadeControlIndex);
    5815          18 :                             ConstrNumSh = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
    5816             :                         }
    5817             :                     }
    5818             :                 }
    5819             :             }
    5820             : 
    5821             :             // Error checks for shades and blinds
    5822             : 
    5823         155 :             ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    5824         155 :             if (!ErrorsFound && WSCPtr > 0 && ConstrNum > 0 && ConstrNumSh > 0) {
    5825             : 
    5826         155 :                 if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5827          88 :                     TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
    5828          88 :                     TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
    5829          88 :                     if (TotShLayers - 1 != TotLayers) {
    5830           0 :                         ShowWarningError(
    5831             :                             state,
    5832             :                             "WindowShadingControl: Interior shade or blind: Potential problem in match of unshaded/shaded constructions, "
    5833             :                             "shaded should have 1 more layers than unshaded.");
    5834           0 :                         ShowContinueError(state, format("Unshaded construction={}", state.dataConstruction->Construct(ConstrNum).Name));
    5835           0 :                         ShowContinueError(state, format("Shaded construction={}", state.dataConstruction->Construct(ConstrNumSh).Name));
    5836           0 :                         ShowContinueError(state,
    5837             :                                           "If preceding two constructions are same name, you have likely specified a WindowShadingControl (Field #3) "
    5838             :                                           "with the Window Construction rather than a shaded construction.");
    5839             :                     }
    5840         248 :                     for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    5841         160 :                         if (state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay) !=
    5842         160 :                             state.dataConstruction->Construct(ConstrNumSh).LayerPoint(Lay)) {
    5843           0 :                             ErrorsFound = true;
    5844           0 :                             ShowSevereError(state,
    5845           0 :                                             format(" The glass and gas layers in the shaded and unshaded constructions do not match for window={}",
    5846           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5847           0 :                             ShowContinueError(state, format("Unshaded construction={}", state.dataConstruction->Construct(ConstrNum).Name));
    5848           0 :                             ShowContinueError(state, format("Shaded construction={}", state.dataConstruction->Construct(ConstrNumSh).Name));
    5849           0 :                             break;
    5850             :                         }
    5851             :                     }
    5852             :                 }
    5853             : 
    5854         155 :                 if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5855          28 :                     TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
    5856          28 :                     TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
    5857          28 :                     if (TotShLayers - 1 != TotLayers) {
    5858           0 :                         ShowWarningError(state,
    5859             :                                          "WindowShadingControl: Exterior shade, screen or blind: Potential problem in match of unshaded/shaded "
    5860             :                                          "constructions, shaded should have 1 more layer than unshaded.");
    5861           0 :                         ShowContinueError(state, format("Unshaded construction={}", state.dataConstruction->Construct(ConstrNum).Name));
    5862           0 :                         ShowContinueError(state, format("Shaded construction={}", state.dataConstruction->Construct(ConstrNumSh).Name));
    5863           0 :                         ShowContinueError(
    5864             :                             state,
    5865             :                             "If preceding two constructions have the same name, you have likely specified a WindowShadingControl (Field "
    5866             :                             "#3) with the Window Construction rather than a shaded construction.");
    5867             :                     }
    5868          76 :                     for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    5869          48 :                         if (state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay) !=
    5870          48 :                             state.dataConstruction->Construct(ConstrNumSh).LayerPoint(Lay + 1)) {
    5871           0 :                             ErrorsFound = true;
    5872           0 :                             ShowSevereError(state,
    5873           0 :                                             format(" The glass and gas layers in the shaded and unshaded constructions do not match for window={}",
    5874           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5875           0 :                             ShowContinueError(state, format("Unshaded construction={}", state.dataConstruction->Construct(ConstrNum).Name));
    5876           0 :                             ShowContinueError(state, format("Shaded construction={}", state.dataConstruction->Construct(ConstrNumSh).Name));
    5877           0 :                             break;
    5878             :                         }
    5879             :                     }
    5880             :                 }
    5881             : 
    5882         155 :                 if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    5883             :                     // Divider not allowed with between-glass shade or blind
    5884           9 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
    5885           0 :                         if (state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth > 0.0) {
    5886           0 :                             ShowWarningError(
    5887           0 :                                 state, format("A divider cannot be specified for window {}", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    5888           0 :                             ShowContinueError(state, ", which has a between-glass shade or blind.");
    5889           0 :                             ShowContinueError(state, "Calculation will proceed without the divider for this window.");
    5890           0 :                             state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth = 0.0;
    5891             :                         }
    5892             :                     }
    5893             :                     // Check consistency of gap widths between unshaded and shaded constructions
    5894           9 :                     TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
    5895           9 :                     TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
    5896           9 :                     TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
    5897           9 :                     if (TotShLayers - 2 != TotLayers) {
    5898           0 :                         ShowWarningError(
    5899             :                             state,
    5900             :                             "WindowShadingControl: Between Glass Shade/Blind: Potential problem in match of unshaded/shaded constructions, "
    5901             :                             "shaded should have 2 more layers than unshaded.");
    5902           0 :                         ShowContinueError(state, format("Unshaded construction={}", state.dataConstruction->Construct(ConstrNum).Name));
    5903           0 :                         ShowContinueError(state, format("Shaded construction={}", state.dataConstruction->Construct(ConstrNumSh).Name));
    5904           0 :                         ShowContinueError(state,
    5905             :                                           "If preceding two constructions are same name, you have likely specified a WindowShadingControl (Field #3) "
    5906             :                                           "with the Window Construction rather than a shaded construction.");
    5907             :                     }
    5908           9 :                     if (state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayers) !=
    5909           9 :                         state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotShLayers)) {
    5910           0 :                         ShowSevereError(state, format("{}: Mis-match in unshaded/shaded inside layer materials.  These should match.", cRoutineName));
    5911           0 :                         ShowContinueError(
    5912             :                             state,
    5913           0 :                             format("Unshaded construction={}, Material={}",
    5914           0 :                                    state.dataConstruction->Construct(ConstrNum).Name,
    5915           0 :                                    state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayers))->Name));
    5916           0 :                         ShowContinueError(
    5917             :                             state,
    5918           0 :                             format("Shaded construction={}, Material={}",
    5919           0 :                                    state.dataConstruction->Construct(ConstrNumSh).Name,
    5920           0 :                                    state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotShLayers))->Name));
    5921           0 :                         ErrorsFound = true;
    5922             :                     }
    5923           9 :                     if (state.dataConstruction->Construct(ConstrNum).LayerPoint(1) != state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1)) {
    5924           0 :                         ShowSevereError(state, format("{}: Mis-match in unshaded/shaded inside layer materials.  These should match.", cRoutineName));
    5925           0 :                         ShowContinueError(state,
    5926           0 :                                           format("Unshaded construction={}, Material={}",
    5927           0 :                                                  state.dataConstruction->Construct(ConstrNum).Name,
    5928           0 :                                                  state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(1))->Name));
    5929           0 :                         ShowContinueError(state,
    5930           0 :                                           format("Shaded construction={}, Material={}",
    5931           0 :                                                  state.dataConstruction->Construct(ConstrNumSh).Name,
    5932           0 :                                                  state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1))->Name));
    5933           0 :                         ErrorsFound = true;
    5934             :                     }
    5935           9 :                     if (TotGlassLayers == 2 || TotGlassLayers == 3) {
    5936           9 :                         MatGap = state.dataConstruction->Construct(ConstrNum).LayerPoint(2 * TotGlassLayers - 2);
    5937           9 :                         MatGap1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers - 2);
    5938           9 :                         MatGap2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers);
    5939           9 :                         MatSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers - 1);
    5940           9 :                         if (state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::BGBlind) {
    5941           5 :                             MatGapCalc =
    5942           5 :                                 std::abs(state.dataMaterial->Material(MatGap)->Thickness -
    5943           5 :                                          (state.dataMaterial->Material(MatGap1)->Thickness + state.dataMaterial->Material(MatGap2)->Thickness));
    5944           5 :                             if (MatGapCalc > 0.001) {
    5945           0 :                                 ShowSevereError(state,
    5946           0 :                                                 format("{}: The gap width(s) for the unshaded window construction {}",
    5947             :                                                        cRoutineName,
    5948           0 :                                                        state.dataConstruction->Construct(ConstrNum).Name));
    5949           0 :                                 ShowContinueError(state,
    5950           0 :                                                   "are inconsistent with the gap widths for shaded window construction " +
    5951           0 :                                                       state.dataConstruction->Construct(ConstrNumSh).Name);
    5952           0 :                                 ShowContinueError(state,
    5953           0 :                                                   "for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5954             :                                                       ", which has a between-glass blind.");
    5955           0 :                                 ShowContinueError(state,
    5956           0 :                                                   format("..Material={} thickness={:.3R} -",
    5957           0 :                                                          state.dataMaterial->Material(MatGap)->Name,
    5958           0 :                                                          state.dataMaterial->Material(MatGap)->Thickness));
    5959           0 :                                 ShowContinueError(state,
    5960           0 :                                                   format("..( Material={} thickness={:.3R} +",
    5961           0 :                                                          state.dataMaterial->Material(MatGap1)->Name,
    5962           0 :                                                          state.dataMaterial->Material(MatGap1)->Thickness));
    5963           0 :                                 ShowContinueError(state,
    5964           0 :                                                   format("..Material={} thickness={:.3R} )=[{:.3R}] >.001",
    5965           0 :                                                          state.dataMaterial->Material(MatGap2)->Name,
    5966           0 :                                                          state.dataMaterial->Material(MatGap2)->Thickness,
    5967             :                                                          MatGapCalc));
    5968           0 :                                 ErrorsFound = true;
    5969             :                             }
    5970             :                         } else { // Between-glass shade
    5971           4 :                             MatGapCalc =
    5972           4 :                                 std::abs(state.dataMaterial->Material(MatGap)->Thickness -
    5973           4 :                                          (state.dataMaterial->Material(MatGap1)->Thickness + state.dataMaterial->Material(MatGap2)->Thickness +
    5974           4 :                                           state.dataMaterial->Material(MatSh)->Thickness));
    5975           4 :                             if (MatGapCalc > 0.001) {
    5976           0 :                                 ShowSevereError(state,
    5977           0 :                                                 format("{}: The gap width(s) for the unshaded window construction {}",
    5978             :                                                        cRoutineName,
    5979           0 :                                                        state.dataConstruction->Construct(ConstrNum).Name));
    5980           0 :                                 ShowContinueError(state,
    5981           0 :                                                   "are inconsistent with the gap widths for shaded window construction " +
    5982           0 :                                                       state.dataConstruction->Construct(ConstrNumSh).Name);
    5983           0 :                                 ShowContinueError(state,
    5984           0 :                                                   "for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
    5985             :                                                       ", which has a between-glass shade.");
    5986           0 :                                 ShowContinueError(state,
    5987           0 :                                                   format("..Material={} thickness={:.3R} -",
    5988           0 :                                                          state.dataMaterial->Material(MatGap)->Name,
    5989           0 :                                                          state.dataMaterial->Material(MatGap)->Thickness));
    5990           0 :                                 ShowContinueError(state,
    5991           0 :                                                   format("...( Material={} thickness={:.3R} +",
    5992           0 :                                                          state.dataMaterial->Material(MatGap1)->Name,
    5993           0 :                                                          state.dataMaterial->Material(MatGap1)->Thickness));
    5994           0 :                                 ShowContinueError(state,
    5995           0 :                                                   format("..Material={} thickness={:.3R} +",
    5996           0 :                                                          state.dataMaterial->Material(MatGap2)->Name,
    5997           0 :                                                          state.dataMaterial->Material(MatGap2)->Thickness));
    5998           0 :                                 ShowContinueError(state,
    5999           0 :                                                   format("..Material={} thickness={:.3R} )=[{:.3R}] >.001",
    6000           0 :                                                          state.dataMaterial->Material(MatSh)->Name,
    6001           0 :                                                          state.dataMaterial->Material(MatSh)->Thickness,
    6002             :                                                          MatGapCalc));
    6003           0 :                                 ErrorsFound = true;
    6004             :                             }
    6005             :                         }
    6006             :                     }
    6007             :                 }
    6008             :             }
    6009             :         }
    6010        6207 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    6011        6207 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides != 3) { // Rectangular Window
    6012             :             // Initialize the FrameDivider number for this window. W5FrameDivider will be positive if
    6013             :             // this window's construction came from the Window5 data file and that construction had an
    6014             :             // associated frame or divider. It will be zero if the window's construction is not from the
    6015             :             // Window5 data file, or the construction is from the data file, but the construction has no
    6016             :             // associated frame or divider. Note that if there is a FrameDivider candidate for this
    6017             :             // window from the Window5 data file it is used instead of the window's input FrameDivider.
    6018             : 
    6019        6205 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    6020        6205 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider =
    6021        6205 :                     state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).W5FrameDivider;
    6022             : 
    6023             :                 // Warning if FrameAndDivider for this window is over-ridden by one from Window5 Data File
    6024        6205 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0 && !state.dataIPShortCut->lAlphaFieldBlanks(FrameField)) {
    6025           0 :                     ShowSevereError(state,
    6026           0 :                                     format("{}=\"{}\", {}=\"{}\"",
    6027             :                                            cCurrentModuleObject,
    6028           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6029           0 :                                            state.dataIPShortCut->cAlphaFieldNames(FrameField),
    6030           0 :                                            state.dataIPShortCut->cAlphaArgs(FrameField)));
    6031           0 :                     ShowContinueError(state,
    6032           0 :                                       format("will be replaced with FrameAndDivider from Window5 Data File entry {}",
    6033           0 :                                              state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name));
    6034             :                 }
    6035             : 
    6036        6205 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(FrameField) && state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider == 0) {
    6037         373 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider =
    6038         373 :                         Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(FrameField), state.dataSurface->FrameDivider);
    6039         373 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider == 0) {
    6040           0 :                         if (!state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
    6041           0 :                             ShowSevereError(state,
    6042           0 :                                             format("{}=\"{}\", invalid {}=\"{}\"",
    6043             :                                                    cCurrentModuleObject,
    6044           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6045           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(FrameField),
    6046           0 :                                                    state.dataIPShortCut->cAlphaArgs(FrameField)));
    6047           0 :                             ErrorsFound = true;
    6048             :                         } else {
    6049           0 :                             ShowSevereError(state,
    6050           0 :                                             format("{}=\"{}\", invalid {}=\"{}\"",
    6051             :                                                    cCurrentModuleObject,
    6052           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6053           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(FrameField),
    6054           0 :                                                    state.dataIPShortCut->cAlphaArgs(FrameField)));
    6055           0 :                             ShowContinueError(state, "...Frame/Divider is not supported in Equivalent Layer Window model.");
    6056             :                         }
    6057             :                     }
    6058             :                     // Divider not allowed with between-glass shade or blind
    6059         414 :                     for (int WSCPtr : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList) {
    6060          41 :                         if (!ErrorsFound && WSCPtr > 0 && ConstrNumSh > 0) {
    6061          41 :                             if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
    6062           1 :                                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
    6063           1 :                                     if (state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth >
    6064             :                                         0.0) {
    6065           0 :                                         ShowSevereError(state,
    6066           0 :                                                         format("{}=\"{}\", invalid {}=\"{}\"",
    6067             :                                                                cCurrentModuleObject,
    6068           0 :                                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6069           0 :                                                                state.dataIPShortCut->cAlphaFieldNames(FrameField),
    6070           0 :                                                                state.dataIPShortCut->cAlphaArgs(FrameField)));
    6071           0 :                                         ShowContinueError(state,
    6072             :                                                           "Divider cannot be specified because the construction has a between-glass shade or blind.");
    6073           0 :                                         ShowContinueError(state, "Calculation will proceed without the divider for this window.");
    6074           0 :                                         ShowContinueError(
    6075             :                                             state,
    6076           0 :                                             format("Divider width = [{:.2R}].",
    6077           0 :                                                    state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider)
    6078           0 :                                                        .DividerWidth));
    6079           0 :                                         state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth =
    6080             :                                             0.0;
    6081             :                                     }
    6082             :                                 } // End of check if window has divider
    6083             :                             }     // End of check if window has a between-glass shade or blind
    6084             :                         }         // End of check if window has a shaded construction
    6085         373 :                     }             // end of looping through window shading controls of window
    6086             :                 }                 // End of check if window has an associated FrameAndDivider
    6087             :             }                     // End of check if window has a construction
    6088             :         }
    6089             : 
    6090        6207 :         if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
    6091           3 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
    6092             :                 // Equivalent Layer window does not have frame/divider model
    6093           0 :                 ShowSevereError(state,
    6094           0 :                                 format("{}=\"{}\", invalid {}=\"{}\"",
    6095             :                                        cCurrentModuleObject,
    6096           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6097           0 :                                        state.dataIPShortCut->cAlphaFieldNames(FrameField),
    6098           0 :                                        state.dataIPShortCut->cAlphaArgs(FrameField)));
    6099           0 :                 ShowContinueError(state, "Frame/Divider is not supported in Equivalent Layer Window model.");
    6100           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider = 0;
    6101             :             }
    6102             :         }
    6103        6207 :     }
    6104             : 
    6105        6694 :     void CheckSubSurfaceMiscellaneous(EnergyPlusData &state,
    6106             :                                       std::string_view const cRoutineName,       // routine name calling this one (for error messages)
    6107             :                                       bool &ErrorsFound,                         // true if errors have been found or are found here
    6108             :                                       int const SurfNum,                         // current surface number
    6109             :                                       std::string const &SubSurfaceName,         // name of the surface
    6110             :                                       std::string const &SubSurfaceConstruction, // name of the construction
    6111             :                                       int &AddedSubSurfaces)
    6112             :     {
    6113             : 
    6114             :         // SUBROUTINE INFORMATION:
    6115             :         //       AUTHOR         Linda Lawrie
    6116             :         //       DATE WRITTEN   December 2008
    6117             :         //       MODIFIED       na
    6118             :         //       RE-ENGINEERED  na
    6119             : 
    6120             :         // PURPOSE OF THIS SUBROUTINE:
    6121             :         // This routine performs miscellaneous checks on subsurfaces: Windows, GlassDoors, Doors, Tubular Devices.
    6122             : 
    6123             :         // Using/Aliasing
    6124             : 
    6125             :         using namespace DataErrorTracking;
    6126             : 
    6127             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6128             :         int NumShades; // count on number of shading layers
    6129             :         int Lay;       // Layer number
    6130             :         int LayerPtr;  // Layer pointer
    6131             :         int ConstrNum; // Construction number
    6132             :         int Found;     // when item is found
    6133             : 
    6134             :         // Warning if window has multiplier > 1 and SolarDistribution = FullExterior or FullInteriorExterior
    6135             : 
    6136        6694 :         if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6137        1019 :              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) &&
    6138       13127 :             static_cast<int>(state.dataHeatBal->SolarDistribution) > static_cast<int>(DataHeatBalance::Shadowing::Minimal) &&
    6139        5414 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier > 1.0) {
    6140           6 :             if (state.dataGlobal->DisplayExtraWarnings) {
    6141           0 :                 ShowWarningError(
    6142             :                     state,
    6143           0 :                     format("{}: A Multiplier > 1.0 for window/glass door {}", cRoutineName, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    6144           0 :                 ShowContinueError(state, "in conjunction with SolarDistribution = FullExterior or FullInteriorExterior");
    6145           0 :                 ShowContinueError(state, "can cause inaccurate shadowing on the window and/or");
    6146           0 :                 ShowContinueError(state, "inaccurate interior solar distribution from the window.");
    6147             :             }
    6148           6 :             ++state.dataErrTracking->TotalMultipliedWindows;
    6149             :         }
    6150             : 
    6151             :         //  Require that a construction referenced by a surface that is a window
    6152             :         //  NOT have a shading device layer; use WindowShadingControl to specify a shading device.
    6153        6694 :         ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    6154        6694 :         if (ConstrNum > 0) {
    6155        6694 :             NumShades = 0;
    6156       17582 :             for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    6157       10888 :                 LayerPtr = state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay);
    6158       10888 :                 if (LayerPtr == 0) continue; // Error is caught already, will terminate later
    6159       10888 :                 if (state.dataMaterial->Material(LayerPtr)->group == Material::Group::Shade ||
    6160       21776 :                     state.dataMaterial->Material(LayerPtr)->group == Material::Group::WindowBlind ||
    6161       10888 :                     state.dataMaterial->Material(LayerPtr)->group == Material::Group::Screen)
    6162           0 :                     ++NumShades;
    6163             :             }
    6164        6694 :             if (NumShades != 0) {
    6165           0 :                 ShowSevereError(state, format("{}: Window \"{}\" must not directly reference", cRoutineName, SubSurfaceName));
    6166           0 :                 ShowContinueError(state, format("a Construction (i.e, \"{}\") with a shading device.", SubSurfaceConstruction));
    6167           0 :                 ShowContinueError(state, "Use WindowShadingControl to specify a shading device for a window.");
    6168           0 :                 ErrorsFound = true;
    6169             :             }
    6170             :         }
    6171             : 
    6172             :         // Disallow glass transmittance dirt factor for interior windows and glass doors
    6173             : 
    6174        6785 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment &&
    6175          91 :             (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6176          80 :              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor)) {
    6177          12 :             ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
    6178          12 :             if (ConstrNum > 0) {
    6179          24 :                 for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
    6180          12 :                     LayerPtr = state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay);
    6181          12 :                     auto const *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(LayerPtr));
    6182          12 :                     assert(thisMaterial != nullptr);
    6183          12 :                     if (thisMaterial->group == Material::Group::WindowGlass && thisMaterial->GlassTransDirtFactor < 1.0) {
    6184           0 :                         ShowSevereError(state, format("{}: Interior Window or GlassDoor {} has a glass layer with", cRoutineName, SubSurfaceName));
    6185           0 :                         ShowContinueError(state, "Dirt Correction Factor for Solar and Visible Transmittance < 1.0");
    6186           0 :                         ShowContinueError(state, "A value less than 1.0 for this factor is only allowed for exterior windows and glass doors.");
    6187           0 :                         ErrorsFound = true;
    6188             :                     }
    6189             :                 }
    6190             :             }
    6191             :         }
    6192             : 
    6193             :         // If this is a window with a construction from the Window5DataFile, call routine that will
    6194             :         // (1) if one glazing system on Data File, give warning message if window height or width
    6195             :         //     differ by more than 10% from those of the glazing system on the Data File;
    6196             :         // (2) if two glazing systems (separated by a mullion) on Data File, create a second window
    6197             :         //     and adjust the dimensions of the original and second windows to those on the Data File
    6198             : 
    6199        6694 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
    6200             : 
    6201        6694 :             if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).FromWindow5DataFile) {
    6202             : 
    6203           8 :                 ModifyWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
    6204             : 
    6205             :             } else {
    6206             :                 // Calculate net area for base surface (note that ModifyWindow, above, adjusts net area of
    6207             :                 // base surface for case where window construction is from Window5 Data File
    6208             :                 // In case there is in error in this window's base surface (i.e. none)..
    6209        6686 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf > 0) {
    6210        6686 :                     state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -=
    6211        6686 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6212             : 
    6213             :                     // Subtract TDD:DIFFUSER area from other side interzone surface
    6214        6688 :                     if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser) &&
    6215           2 :                         not_blank(state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf)
    6216             :                                       .ExtBoundCondName)) { // Base surface is an interzone surface
    6217             :                         // Lookup interzone surface of the base surface
    6218             :                         // (Interzone surfaces have not been assigned yet, but all base surfaces should already be loaded.)
    6219           2 :                         Found = Util::FindItemInList(
    6220           2 :                             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).ExtBoundCondName,
    6221           2 :                             state.dataSurfaceGeometry->SurfaceTmp,
    6222             :                             SurfNum);
    6223           2 :                         if (Found != 0) state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6224             :                     }
    6225        6686 :                     if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
    6226           0 :                         ShowSevereError(state,
    6227           0 :                                         format("{}: Surface Openings have too much area for base surface={}",
    6228             :                                                cRoutineName,
    6229           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name));
    6230           0 :                         ShowContinueError(state, format("Opening Surface creating error={}", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    6231           0 :                         ErrorsFound = true;
    6232             :                     }
    6233             :                     // Net area of base surface with unity window multipliers (used in shadowing checks)
    6234             :                     // For Windows, Glass Doors and Doors, just one area is subtracted.  For the rest, should be
    6235             :                     // full area.
    6236        7705 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    6237        1019 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) {
    6238        6205 :                         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
    6239        6205 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    6240         481 :                     } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door) { // Door, TDD:Diffuser, TDD:DOME
    6241         477 :                         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
    6242         477 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    6243             :                     } else {
    6244           4 :                         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
    6245           4 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6246             :                     }
    6247             :                 }
    6248             :             }
    6249             :         }
    6250        6694 :     }
    6251             : 
    6252         118 :     void MakeRelativeRectangularVertices(EnergyPlusData &state,
    6253             :                                          int const BaseSurfNum, // Base surface
    6254             :                                          int const SurfNum,
    6255             :                                          Real64 const XCoord,
    6256             :                                          Real64 const ZCoord,
    6257             :                                          Real64 const Length,
    6258             :                                          Real64 const Height)
    6259             :     {
    6260             : 
    6261             :         // SUBROUTINE INFORMATION:
    6262             :         //       AUTHOR         Linda Lawrie
    6263             :         //       DATE WRITTEN   December 2008
    6264             :         //       MODIFIED       na
    6265             :         //       RE-ENGINEERED  na
    6266             : 
    6267             :         // PURPOSE OF THIS SUBROUTINE:
    6268             :         // This routine creates world/3d coordinates for rectangular surfaces using relative X and Z, length & height.
    6269             : 
    6270             :         // METHODOLOGY EMPLOYED:
    6271             :         // na
    6272             : 
    6273             :         // REFERENCES:
    6274             :         // na
    6275             : 
    6276             :         // Using/Aliasing
    6277             :         using namespace Vectors;
    6278             : 
    6279             :         // Locals
    6280             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    6281             : 
    6282             :         // SUBROUTINE PARAMETER DEFINITIONS:
    6283             :         // na
    6284             : 
    6285             :         // INTERFACE BLOCK SPECIFICATIONS:
    6286             :         // na
    6287             : 
    6288             :         // DERIVED TYPE DEFINITIONS:
    6289             :         // na
    6290             : 
    6291             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6292             :         Real64 SurfAzimuth; // Surface Azimuth/Facing (same as Base Surface)
    6293             :         Real64 SurfTilt;    // Tilt (same as Base Surface)
    6294             :         Real64 XLLC;
    6295             :         Real64 YLLC;
    6296             :         Real64 ZLLC;
    6297             :         Real64 CosSurfAzimuth;
    6298             :         Real64 SinSurfAzimuth;
    6299             :         Real64 CosSurfTilt;
    6300             :         Real64 SinSurfTilt;
    6301             :         Real64 BaseCosSurfAzimuth;
    6302             :         Real64 BaseSinSurfAzimuth;
    6303             :         Real64 BaseCosSurfTilt;
    6304             :         Real64 BaseSinSurfTilt;
    6305         118 :         Array1D<Real64> XX(4);
    6306         118 :         Array1D<Real64> YY(4);
    6307             :         Real64 Perimeter;
    6308             :         int n;
    6309             :         int Vrt;
    6310             : 
    6311         118 :         if (BaseSurfNum == 0) return; // invalid base surface, don't bother
    6312             : 
    6313             :         // Tilt and Facing (Azimuth) will be same as the Base Surface
    6314             : 
    6315         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = Height;
    6316         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = Length;
    6317             : 
    6318         118 :         SurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
    6319         118 :         SurfTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
    6320         118 :         CosSurfAzimuth = std::cos(SurfAzimuth * Constant::DegToRadians);
    6321         118 :         SinSurfAzimuth = std::sin(SurfAzimuth * Constant::DegToRadians);
    6322         118 :         CosSurfTilt = std::cos(SurfTilt * Constant::DegToRadians);
    6323         118 :         SinSurfTilt = std::sin(SurfTilt * Constant::DegToRadians);
    6324         118 :         BaseCosSurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim;
    6325         118 :         BaseSinSurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6326         118 :         BaseCosSurfTilt = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt;
    6327         118 :         BaseSinSurfTilt = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6328             : 
    6329         118 :         XLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x - XCoord * BaseCosSurfAzimuth -
    6330         118 :                ZCoord * BaseCosSurfTilt * BaseSinSurfAzimuth;
    6331         118 :         YLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y + XCoord * BaseSinSurfAzimuth -
    6332         118 :                ZCoord * BaseCosSurfTilt * BaseCosSurfAzimuth;
    6333         118 :         ZLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z + ZCoord * BaseSinSurfTilt;
    6334             : 
    6335         118 :         XX(1) = 0.0;
    6336         118 :         XX(2) = 0.0;
    6337         118 :         XX(3) = Length;
    6338         118 :         XX(4) = Length;
    6339         118 :         YY(1) = Height;
    6340         118 :         YY(4) = Height;
    6341         118 :         YY(3) = 0.0;
    6342         118 :         YY(2) = 0.0;
    6343             : 
    6344         590 :         for (n = 1; n <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++n) {
    6345         472 :             Vrt = n;
    6346         472 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).x = XLLC - XX(n) * CosSurfAzimuth - YY(n) * CosSurfTilt * SinSurfAzimuth;
    6347         472 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).y = YLLC + XX(n) * SinSurfAzimuth - YY(n) * CosSurfTilt * CosSurfAzimuth;
    6348         472 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).z = ZLLC + YY(n) * SinSurfTilt;
    6349             :         }
    6350             : 
    6351         118 :         CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    6352         118 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    6353         118 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    6354         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    6355         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    6356         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    6357         118 :         CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    6358         118 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    6359         118 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    6360         118 :         DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    6361             :                                 SurfAzimuth,
    6362             :                                 SurfTilt,
    6363         118 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    6364         118 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    6365         118 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    6366         118 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    6367         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfAzimuth;
    6368         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    6369         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    6370         118 :             Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6371             :         // Sine and cosine of azimuth and tilt
    6372         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = SinSurfAzimuth;
    6373         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = CosSurfAzimuth;
    6374         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = SinSurfTilt;
    6375         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = CosSurfTilt;
    6376         118 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
    6377         171 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
    6378          53 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door)
    6379          44 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    6380             :         // Outward normal unit vector (pointing away from room)
    6381         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    6382         472 :         for (n = 1; n <= 3; ++n) {
    6383         354 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    6384          27 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    6385         354 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    6386          91 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    6387         354 :             if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    6388         236 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    6389             :         }
    6390             : 
    6391             :         //  IF (SurfaceTmp(SurfNum)%Class == SurfaceClass::Roof .and. SurfTilt > 80.) THEN
    6392             :         //    WRITE(TiltString,'(F5.1)') SurfTilt
    6393             :         //    TiltString=ADJUSTL(TiltString)
    6394             :         //    CALL ShowWarningError(state, format("Roof/Ceiling Tilt={}{}{}{}{}{}{}{}{}{} for Surface={}{}{}, in
    6395             :         //    Zone={}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", //TRIM(TiltString)//',,
    6396             :         //    much, greater, than, expected, tilt, of, 0,'//, &, //, //TRIM(SurfaceTmp(SurfNum)%Name)//, &, //, //TRIM(SurfaceTmp(SurfNum)%ZoneName)),
    6397             :         //    //, ENDIF, //, IF, (SurfaceTmp(SurfNum)%Class, ==, SurfaceClass::Floor, .and., SurfTilt, <, 170.), THEN, //, WRITE(TiltString,'(F5.1)'),
    6398             :         //    SurfTilt, //, TiltString=ADJUSTL(TiltString), //, CALL, ShowWarningError(state, 'Floor Tilt='//TRIM(TiltString)//', much less than
    6399             :         //    expected tilt of 180,'//   &
    6400             :         //                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
    6401             :         //                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName)), //, ENDIF, if,
    6402             :         //                          (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class, ==, SurfaceClass::Window, ||,
    6403             :         //                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class, ==, SurfaceClass::GlassDoor, ||,
    6404             :         //                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class, ==, SurfaceClass::Door),
    6405             :         //                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area, *=,
    6406             :         //                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;, //, Can, perform, tests, on, this, surface, here,
    6407             :         //                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky, =, 0.5, *, (1.0,
    6408             :         //                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt));
    6409             :         // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    6410             :         // surfaces
    6411         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    6412         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    6413             : 
    6414         118 :         Perimeter = distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides),
    6415         118 :                              state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1));
    6416         472 :         for (Vrt = 2; Vrt <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vrt) {
    6417         354 :             Perimeter +=
    6418         354 :                 distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt), state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt - 1));
    6419             :         }
    6420         118 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
    6421             : 
    6422             :         // Call to transform vertices
    6423             : 
    6424         118 :         TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6425         118 :     }
    6426             : 
    6427         796 :     void GetAttShdSurfaceData(EnergyPlusData &state,
    6428             :                               bool &ErrorsFound,   // Error flag indicator (true if errors found)
    6429             :                               int &SurfNum,        // Count of Current SurfaceNumber
    6430             :                               int const TotShdSubs // Number of Attached Shading SubSurfaces to obtain
    6431             :     )
    6432             :     {
    6433             :         // SUBROUTINE INFORMATION:
    6434             :         //       AUTHOR         Linda Lawrie
    6435             :         //       DATE WRITTEN   May 2000
    6436             : 
    6437             :         // PURPOSE OF THIS SUBROUTINE:
    6438             :         // This subroutine gets the HeatTransfer Surface Data,
    6439             :         // checks it for errors, etc.
    6440             : 
    6441             :         // Using/Aliasing
    6442             :         using ScheduleManager::CheckScheduleValueMinMax;
    6443             :         using ScheduleManager::GetScheduleIndex;
    6444             :         using ScheduleManager::GetScheduleMaxValue;
    6445             :         using ScheduleManager::GetScheduleMinValue;
    6446             : 
    6447             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6448             :         int IOStat;     // IO Status when calling get input subroutine
    6449             :         int NumAlphas;  // Number of alpha names being passed
    6450             :         int NumNumbers; // Number of properties being passed
    6451             :         int Found;      // For matching interzone surfaces
    6452             :         int Loop;
    6453             :         Real64 SchedMinValue;
    6454             :         Real64 SchedMaxValue;
    6455             : 
    6456         796 :         if (TotShdSubs > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    6457           1 :             ShowWarningError(state, "Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing");
    6458             :         }
    6459         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    6460         796 :         cCurrentModuleObject = "Shading:Zone:Detailed";
    6461         796 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
    6462         796 :         if (NumAlphas != 3) {
    6463           0 :             ShowSevereError(state,
    6464           0 :                             format("{}: Object Definition indicates not = 3 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
    6465           0 :             ErrorsFound = true;
    6466             :         }
    6467             : 
    6468        1494 :         for (Loop = 1; Loop <= TotShdSubs; ++Loop) {
    6469        1396 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    6470             :                                                                      cCurrentModuleObject,
    6471             :                                                                      Loop,
    6472         698 :                                                                      state.dataIPShortCut->cAlphaArgs,
    6473             :                                                                      NumAlphas,
    6474         698 :                                                                      state.dataIPShortCut->rNumericArgs,
    6475             :                                                                      NumNumbers,
    6476             :                                                                      IOStat,
    6477         698 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    6478         698 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    6479         698 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    6480         698 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    6481             : 
    6482        1396 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    6483         698 :                                                          state.dataSurfaceGeometry->UniqueSurfaceNames,
    6484         698 :                                                          state.dataIPShortCut->cAlphaArgs(1),
    6485             :                                                          cCurrentModuleObject,
    6486         698 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    6487             :                                                          ErrorsFound)) {
    6488           0 :                 continue;
    6489             :             }
    6490             : 
    6491         698 :             ++SurfNum;
    6492         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    6493         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
    6494         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    6495         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(2);
    6496             :             //  The subsurface inherits properties from the base surface
    6497             :             //  Exterior conditions, Zone, etc.
    6498             :             //  We can figure out the base surface though, because they've all been entered
    6499         698 :             Found = Util::FindItemInList(
    6500         698 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
    6501         698 :             if (Found > 0) {
    6502             :                 // SurfaceTmp(SurfNum)%BaseSurf=Found
    6503         698 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    6504         698 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    6505         698 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    6506         698 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
    6507         698 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
    6508         698 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
    6509        1396 :                     state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
    6510             :             } else {
    6511           0 :                 ShowSevereError(state,
    6512           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    6513             :                                        cCurrentModuleObject,
    6514           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6515           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    6516           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    6517           0 :                 ErrorsFound = true;
    6518             :             }
    6519         698 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) {
    6520           0 :                 ShowSevereError(state,
    6521           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    6522             :                                        cCurrentModuleObject,
    6523           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6524           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    6525           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    6526           0 :                 ShowContinueError(state, "...trying to attach a shading device to an interzone surface.");
    6527           0 :                 ErrorsFound = true;
    6528           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6529             :                     ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6530             :             }
    6531         698 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    6532           0 :                 ShowSevereError(state,
    6533           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    6534             :                                        cCurrentModuleObject,
    6535           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6536           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    6537           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    6538           0 :                 ShowContinueError(state, "...trying to attach a shading device to an interior surface.");
    6539           0 :                 ErrorsFound = true;
    6540           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6541             :                     ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6542             :             }
    6543             : 
    6544         698 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    6545         635 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    6546         635 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex == 0) {
    6547           0 :                     ShowSevereError(state,
    6548           0 :                                     format("{}=\"{}\", {} not found=\"{}",
    6549             :                                            cCurrentModuleObject,
    6550           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6551           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    6552           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    6553           0 :                     ErrorsFound = true;
    6554             :                 }
    6555             :             } else {
    6556          63 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    6557             :             }
    6558         698 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex != 0) {
    6559         635 :                 if (!CheckScheduleValueMinMax(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex, ">=", 0.0, "<=", 1.0)) {
    6560           0 :                     ShowSevereError(state,
    6561           0 :                                     format("{}=\"{}\", {}=\"{}\", values not in range [0,1].",
    6562             :                                            cCurrentModuleObject,
    6563           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6564           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    6565           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    6566           0 :                     ErrorsFound = true;
    6567             :                 }
    6568         635 :                 SchedMinValue = GetScheduleMinValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    6569         635 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue = SchedMinValue;
    6570         635 :                 SchedMaxValue = GetScheduleMaxValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
    6571         635 :                 if (SchedMinValue == 1.0) {
    6572             :                     // Set transparent for now, check for EMS actuators later in SolarShading::resetShadingSurfaceTransparency
    6573           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent = true;
    6574             :                 }
    6575         635 :                 if (SchedMinValue < 0.0) {
    6576           0 :                     ShowSevereError(state,
    6577           0 :                                     format("{}=\"{}\", {}=\"{}\", has schedule values < 0.",
    6578             :                                            cCurrentModuleObject,
    6579           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6580           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    6581           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    6582           0 :                     ShowContinueError(state, "...Schedule values < 0 have no meaning for shading elements.");
    6583             :                 }
    6584         635 :                 if (SchedMaxValue > 0.0) {
    6585           8 :                     state.dataSolarShading->anyScheduledShadingSurface = true;
    6586             :                 }
    6587         635 :                 if (SchedMaxValue > 1.0) {
    6588           0 :                     ShowSevereError(state,
    6589           0 :                                     format("{}=\"{}\", {}=\"{}\", has schedule values > 1.",
    6590             :                                            cCurrentModuleObject,
    6591           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6592           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    6593           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    6594           0 :                     ShowContinueError(state, "...Schedule values > 1 have no meaning for shading elements.");
    6595             :                 }
    6596         635 :                 if (std::abs(SchedMinValue - SchedMaxValue) > Constant::OneMillionth) {
    6597           0 :                     state.dataSurface->ShadingTransmittanceVaries = true;
    6598             :                 }
    6599             :             }
    6600         698 :             if (state.dataIPShortCut->lNumericFieldBlanks(1) || state.dataIPShortCut->rNumericArgs(1) == Constant::AutoCalculate) {
    6601           2 :                 state.dataIPShortCut->rNumericArgs(1) = (NumNumbers - 1) / 3;
    6602           2 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
    6603           2 :                 if (mod(NumNumbers - 1, 3) != 0) {
    6604           0 :                     ShowWarningError(state,
    6605           0 :                                      format("{}=\"{}\", {}",
    6606             :                                             cCurrentModuleObject,
    6607           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6608           0 :                                             format("{} not even multiple of 3. Will read in {}",
    6609           0 :                                                    state.dataIPShortCut->cNumericFieldNames(1),
    6610           0 :                                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides)));
    6611             :                 }
    6612           2 :                 if (state.dataIPShortCut->rNumericArgs(1) < 3) {
    6613           0 :                     ShowSevereError(state,
    6614           0 :                                     format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
    6615             :                                            cCurrentModuleObject,
    6616           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6617           0 :                                            state.dataIPShortCut->cNumericFieldNames(1),
    6618           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
    6619           0 :                     ErrorsFound = true;
    6620           0 :                     continue;
    6621             :                 }
    6622             :             } else {
    6623         696 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
    6624             :             }
    6625         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6626        2094 :             GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({2, _}));
    6627         698 :             CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6628             :             //    IF (SurfaceTmp(SurfNum)%Sides == 3) THEN
    6629             :             //      CALL ShowWarningError(state, TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
    6630             :             //                        ' should not be triangular.')
    6631             :             //      CALL ShowContinueError(state, '...Check results carefully.')
    6632             :             //      ErrorsFound=.TRUE.
    6633             :             //    ENDIF
    6634             :             // Reset surface to be "detached"
    6635         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6636             :             //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6637         698 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6638             :             // SurfaceTmp(SurfNum)%ZoneName='  '
    6639         698 :             if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6640         698 :                 MakeMirrorSurface(state, SurfNum);
    6641             :             }
    6642             :         }
    6643         796 :     }
    6644             : 
    6645         796 :     void GetSimpleShdSurfaceData(EnergyPlusData &state,
    6646             :                                  bool &ErrorsFound,                // Error flag indicator (true if errors found)
    6647             :                                  int &SurfNum,                     // Count of Current SurfaceNumber
    6648             :                                  int const TotOverhangs,           // Number of Overhangs to obtain
    6649             :                                  int const TotOverhangsProjection, // Number of Overhangs (projection) to obtain
    6650             :                                  int const TotFins,                // Number of Fins to obtain
    6651             :                                  int const TotFinsProjection       // Number of Fins (projection) to obtain
    6652             :     )
    6653             :     {
    6654             : 
    6655             :         // SUBROUTINE INFORMATION:
    6656             :         //       AUTHOR         Linda Lawrie
    6657             :         //       DATE WRITTEN   January 2009
    6658             :         //       MODIFIED       na
    6659             :         //       RE-ENGINEERED  na
    6660             : 
    6661             :         // PURPOSE OF THIS SUBROUTINE:
    6662             :         // Get simple overhang and fin descriptions.
    6663             : 
    6664             :         // Using/Aliasing
    6665             :         using namespace Vectors;
    6666             : 
    6667             :         // SUBROUTINE PARAMETER DEFINITIONS:
    6668         796 :         static Array1D_string const cModuleObjects(4, {"Shading:Overhang", "Shading:Overhang:Projection", "Shading:Fin", "Shading:Fin:Projection"});
    6669             : 
    6670             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    6671             :         int Item;
    6672             :         int ItemsToGet;
    6673             :         int Loop;
    6674             :         int NumAlphas;
    6675             :         int NumNumbers;
    6676             :         int IOStat; // IO Status when calling get input subroutine
    6677             :         int Found;  // For matching base surfaces
    6678             :         Real64 Depth;
    6679             :         Real64 Length;
    6680             :         Real64 Xp;
    6681             :         Real64 Yp;
    6682             :         Real64 Zp;
    6683             :         Real64 XLLC;
    6684             :         Real64 YLLC;
    6685             :         int BaseSurfNum;
    6686             :         Real64 TiltAngle;
    6687             :         bool MakeFin;
    6688             : 
    6689         805 :         if ((TotOverhangs + TotOverhangsProjection + TotFins + TotFinsProjection) > 0 &&
    6690           9 :             state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    6691           0 :             ShowWarningError(state, "Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing");
    6692             :         }
    6693         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    6694        3980 :         for (Item = 1; Item <= 4; ++Item) {
    6695             : 
    6696        3184 :             cCurrentModuleObject = cModuleObjects(Item);
    6697        3184 :             if (Item == 1) {
    6698         796 :                 ItemsToGet = TotOverhangs;
    6699        2388 :             } else if (Item == 2) {
    6700         796 :                 ItemsToGet = TotOverhangsProjection;
    6701        1592 :             } else if (Item == 3) {
    6702         796 :                 ItemsToGet = TotFins;
    6703             :             } else { // ! (Item == 4) THEN
    6704         796 :                 ItemsToGet = TotFinsProjection;
    6705             :             }
    6706             : 
    6707        3219 :             for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
    6708          70 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    6709             :                                                                          cCurrentModuleObject,
    6710             :                                                                          Loop,
    6711          35 :                                                                          state.dataIPShortCut->cAlphaArgs,
    6712             :                                                                          NumAlphas,
    6713          35 :                                                                          state.dataIPShortCut->rNumericArgs,
    6714             :                                                                          NumNumbers,
    6715             :                                                                          IOStat,
    6716          35 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    6717          35 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    6718          35 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    6719          35 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    6720             : 
    6721          70 :                 if (GlobalNames::VerifyUniqueInterObjectName(state,
    6722          35 :                                                              state.dataSurfaceGeometry->UniqueSurfaceNames,
    6723          35 :                                                              state.dataIPShortCut->cAlphaArgs(1),
    6724             :                                                              cCurrentModuleObject,
    6725          35 :                                                              state.dataIPShortCut->cAlphaFieldNames(1),
    6726             :                                                              ErrorsFound)) {
    6727           0 :                     continue;
    6728             :                 }
    6729             : 
    6730          35 :                 ++SurfNum;
    6731          35 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
    6732          35 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
    6733          35 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    6734             :                 // this object references a window or door....
    6735             :                 Found =
    6736          35 :                     Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
    6737          35 :                 if (Found > 0) {
    6738          35 :                     BaseSurfNum = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurf;
    6739          35 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurfName;
    6740          35 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    6741          35 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    6742          35 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    6743          35 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
    6744          35 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
    6745          35 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
    6746          70 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
    6747             :                 } else {
    6748           0 :                     ShowSevereError(state,
    6749           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    6750             :                                            cCurrentModuleObject,
    6751           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6752           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    6753           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    6754           0 :                     ErrorsFound = true;
    6755           0 :                     continue;
    6756             :                 }
    6757          35 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) {
    6758           0 :                     ShowSevereError(state,
    6759           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    6760             :                                            cCurrentModuleObject,
    6761           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6762           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    6763           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    6764           0 :                     ShowContinueError(state, "...trying to attach a shading device to an interzone surface.");
    6765           0 :                     ErrorsFound = true;
    6766           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6767             :                         ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6768             :                 }
    6769          35 :                 if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
    6770           0 :                     ShowSevereError(state,
    6771           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    6772             :                                            cCurrentModuleObject,
    6773           0 :                                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    6774           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    6775           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    6776           0 :                     ShowContinueError(state, "...trying to attach a shading device to an interior surface.");
    6777           0 :                     ErrorsFound = true;
    6778           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
    6779             :                         ExternalEnvironment; // reset so program won't crash during "add surfaces"
    6780             :                 }
    6781             : 
    6782          35 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    6783             : 
    6784             :                 //===== Overhang =====
    6785             : 
    6786          35 :                 if (Item < 3) {
    6787             :                     //  Found is the surface window or door.
    6788             :                     //   N1,  \field Height above Window or Door
    6789             :                     //        \units m
    6790             :                     //   N2,  \field Tilt Angle from Window/Door
    6791             :                     //        \units deg
    6792             :                     //        \default 90
    6793             :                     //        \minimum 0
    6794             :                     //        \maximum 180
    6795             :                     //   N3,  \field Left extension from Window/Door Width
    6796             :                     //        \units m
    6797             :                     //   N4,  \field Right extension from Window/Door Width
    6798             :                     //        \note N3 + N4 + Window/Door Width is Overhang Length
    6799             :                     //        \units m
    6800             :                     //   N5;  \field Depth
    6801             :                     //        \units m
    6802             :                     // for projection option:
    6803             :                     //   N5;  \field Depth as Fraction of Window/Door Height
    6804             :                     //        \units m
    6805          26 :                     Length = state.dataIPShortCut->rNumericArgs(3) + state.dataIPShortCut->rNumericArgs(4) +
    6806          26 :                              state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
    6807          26 :                     if (Item == 1) {
    6808          25 :                         Depth = state.dataIPShortCut->rNumericArgs(5);
    6809           1 :                     } else if (Item == 2) {
    6810           1 :                         Depth = state.dataIPShortCut->rNumericArgs(5) * state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
    6811             :                     }
    6812             : 
    6813          26 :                     if (Length * Depth <= 0.0) {
    6814           0 :                         ShowSevereError(state,
    6815           0 :                                         format("{}=\"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
    6816             :                                                cCurrentModuleObject,
    6817           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
    6818           0 :                                                Length * Depth));
    6819           0 :                         continue;
    6820             :                     }
    6821             : 
    6822          26 :                     TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt + state.dataIPShortCut->rNumericArgs(2);
    6823          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
    6824          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    6825          26 :                         Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6826          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth;
    6827             : 
    6828             :                     // Make it relative to surface origin.....
    6829          26 :                     Xp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
    6830          26 :                     Yp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
    6831          26 :                     Zp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
    6832             : 
    6833          26 :                     XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
    6834          26 :                            Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6835             : 
    6836          26 :                     YLLC =
    6837          26 :                         -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
    6838          26 :                             state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
    6839          26 :                         Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
    6840          26 :                         Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6841             : 
    6842          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    6843          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6844             : 
    6845          52 :                     MakeRelativeRectangularVertices(state,
    6846             :                                                     BaseSurfNum,
    6847             :                                                     SurfNum,
    6848          26 :                                                     XLLC - state.dataIPShortCut->rNumericArgs(3),
    6849          26 :                                                     YLLC + state.dataSurfaceGeometry->SurfaceTmp(Found).Height +
    6850          26 :                                                         state.dataIPShortCut->rNumericArgs(1),
    6851             :                                                     Length,
    6852             :                                                     Depth);
    6853             : 
    6854             :                     // Reset surface to be "detached"
    6855             :                     //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6856             :                     //    SurfaceTmp(SurfNum)%ZoneName='  '
    6857             : 
    6858          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6859          26 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6860             : 
    6861             :                     // and mirror
    6862          26 :                     if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6863          26 :                         MakeMirrorSurface(state, SurfNum);
    6864             :                     }
    6865             : 
    6866             :                 } else { // Fins
    6867             : 
    6868             :                     //===== Fins =====
    6869             : 
    6870             :                     //===== Left Fin =====
    6871             : 
    6872             :                     //   N1,  \field Left Extension from Window/Door
    6873             :                     //        \units m
    6874             :                     //   N2,  \field Left Distance Above Top of Window
    6875             :                     //        \units m
    6876             :                     //   N3,  \field Left Distance Below Bottom of Window
    6877             :                     //        \units m
    6878             :                     //        \note N2 + N3 + height of Window/Door is height of Fin
    6879             :                     //   N4,  \field Left Tilt Angle from Window/Door
    6880             :                     //        \units deg
    6881             :                     //        \default 90
    6882             :                     //        \minimum 0
    6883             :                     //        \maximum 180
    6884             :                     //   N5,  \field Left Depth
    6885             :                     //        \units m
    6886             :                     // for projection option:
    6887             :                     //   N5,  \field Left Depth as Fraction of Window/Door Width
    6888             :                     //        \units m
    6889           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + " Left";
    6890           9 :                     Length = state.dataIPShortCut->rNumericArgs(2) + state.dataIPShortCut->rNumericArgs(3) +
    6891           9 :                              state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
    6892           9 :                     if (Item == 3) {
    6893           8 :                         Depth = state.dataIPShortCut->rNumericArgs(5);
    6894           1 :                     } else if (Item == 4) {
    6895           1 :                         Depth = state.dataIPShortCut->rNumericArgs(5) * state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
    6896             :                     }
    6897             : 
    6898           9 :                     MakeFin = true;
    6899           9 :                     if (Length * Depth <= 0.0) {
    6900           0 :                         ShowWarningError(state,
    6901           0 :                                          format("{}=Left Fin of \"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
    6902             :                                                 cCurrentModuleObject,
    6903           0 :                                                 state.dataIPShortCut->cAlphaArgs(1),
    6904           0 :                                                 Length * Depth));
    6905           0 :                         MakeFin = false;
    6906             :                     }
    6907             : 
    6908           9 :                     if (MakeFin) {
    6909           9 :                         TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
    6910           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
    6911           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    6912           9 :                             Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    6913           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth =
    6914           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth - (180.0 - state.dataIPShortCut->rNumericArgs(4));
    6915             : 
    6916             :                         // Make it relative to surface origin.....
    6917             : 
    6918           9 :                         Xp =
    6919           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
    6920           9 :                         Yp =
    6921           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
    6922           9 :                         Zp =
    6923           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
    6924             : 
    6925           9 :                         XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
    6926           9 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    6927             : 
    6928           9 :                         YLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
    6929           9 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
    6930           9 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim *
    6931           9 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
    6932           9 :                                Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    6933             : 
    6934           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim =
    6935           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * Constant::DegToRadians);
    6936           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim =
    6937           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * Constant::DegToRadians);
    6938           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt =
    6939           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * Constant::DegToRadians);
    6940           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt =
    6941           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * Constant::DegToRadians);
    6942             : 
    6943           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    6944           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    6945             : 
    6946          27 :                         MakeRelativeRectangularVertices(state,
    6947             :                                                         BaseSurfNum,
    6948             :                                                         SurfNum,
    6949           9 :                                                         XLLC - state.dataIPShortCut->rNumericArgs(1),
    6950           9 :                                                         YLLC - state.dataIPShortCut->rNumericArgs(3),
    6951             :                                                         -Depth,
    6952             :                                                         Length);
    6953             : 
    6954             :                         // Reset surface to be "detached"
    6955             :                         //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    6956             :                         //    SurfaceTmp(SurfNum)%ZoneName='  '
    6957             : 
    6958           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    6959           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    6960             : 
    6961             :                         // and mirror
    6962           9 :                         if (state.dataReportFlag->MakeMirroredAttachedShading) {
    6963           9 :                             MakeMirrorSurface(state, SurfNum);
    6964             :                         }
    6965             :                     } else {
    6966           0 :                         --SurfNum;
    6967             :                     }
    6968             : 
    6969             :                     //===== Right Fin =====
    6970             : 
    6971             :                     //   N6,  \field Right Extension from Window/Door
    6972             :                     //        \units m
    6973             :                     //   N7,  \field Right Distance Above Top of Window
    6974             :                     //        \units m
    6975             :                     //   N8,  \field Right Distance Below Bottom of Window
    6976             :                     //        \note N7 + N8 + height of Window/Door is height of Fin
    6977             :                     //        \units m
    6978             :                     //   N9,  \field Right Tilt Angle from Window/Door
    6979             :                     //        \units deg
    6980             :                     //        \default 90
    6981             :                     //        \minimum 0
    6982             :                     //        \maximum 180
    6983             :                     //   N10; \field Right Depth
    6984             :                     //        \units m
    6985             :                     // for projection option:
    6986             :                     //   N10; \field Right Depth as Fraction of Window/Door Width
    6987             :                     //        \units m
    6988             : 
    6989           9 :                     ++SurfNum;
    6990           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name =
    6991          18 :                         state.dataIPShortCut->cAlphaArgs(1) + " Right"; // Set the Surface Name in the Derived Type
    6992           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
    6993           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
    6994           9 :                     BaseSurfNum = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurf;
    6995           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurfName;
    6996           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
    6997           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
    6998           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
    6999           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
    7000           9 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
    7001           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
    7002          18 :                         state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
    7003             : 
    7004           9 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
    7005           9 :                     Length = state.dataIPShortCut->rNumericArgs(7) + state.dataIPShortCut->rNumericArgs(8) +
    7006           9 :                              state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
    7007           9 :                     if (Item == 3) {
    7008           8 :                         Depth = state.dataIPShortCut->rNumericArgs(10);
    7009           1 :                     } else if (Item == 4) {
    7010           1 :                         Depth = state.dataIPShortCut->rNumericArgs(10) * state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
    7011             :                     }
    7012             : 
    7013           9 :                     MakeFin = true;
    7014           9 :                     if (Length * Depth <= 0.0) {
    7015           0 :                         ShowWarningError(state,
    7016           0 :                                          format("{}=Right Fin of \"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
    7017             :                                                 cCurrentModuleObject,
    7018           0 :                                                 state.dataIPShortCut->cAlphaArgs(1),
    7019           0 :                                                 Length * Depth));
    7020           0 :                         MakeFin = false;
    7021             :                     }
    7022             : 
    7023           9 :                     if (MakeFin) {
    7024             :                         // Make it relative to surface origin.....
    7025             : 
    7026           9 :                         Xp =
    7027           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
    7028           9 :                         Yp =
    7029           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
    7030           9 :                         Zp =
    7031           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
    7032             : 
    7033           9 :                         XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
    7034           9 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
    7035             : 
    7036           9 :                         YLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
    7037           9 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
    7038           9 :                                Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim *
    7039           9 :                                    state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
    7040           9 :                                Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
    7041             : 
    7042           9 :                         TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
    7043           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
    7044           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    7045           9 :                             Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    7046           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth =
    7047           9 :                             state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth - (180.0 - state.dataIPShortCut->rNumericArgs(9));
    7048           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim =
    7049           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * Constant::DegToRadians);
    7050           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim =
    7051           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * Constant::DegToRadians);
    7052           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt =
    7053           9 :                             std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * Constant::DegToRadians);
    7054           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt =
    7055           9 :                             std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * Constant::DegToRadians);
    7056             : 
    7057           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
    7058           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    7059             : 
    7060          27 :                         MakeRelativeRectangularVertices(state,
    7061             :                                                         BaseSurfNum,
    7062             :                                                         SurfNum,
    7063           9 :                                                         XLLC + state.dataSurfaceGeometry->SurfaceTmp(Found).Width +
    7064           9 :                                                             state.dataIPShortCut->rNumericArgs(6),
    7065           9 :                                                         YLLC - state.dataIPShortCut->rNumericArgs(8),
    7066             :                                                         -Depth,
    7067             :                                                         Length);
    7068             : 
    7069             :                         // Reset surface to be "detached"
    7070             :                         //    SurfaceTmp(SurfNum)%BaseSurfName='  '
    7071             :                         //    SurfaceTmp(SurfNum)%ZoneName='  '
    7072             : 
    7073           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
    7074           9 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
    7075             : 
    7076             :                         // and mirror
    7077           9 :                         if (state.dataReportFlag->MakeMirroredAttachedShading) {
    7078           9 :                             MakeMirrorSurface(state, SurfNum);
    7079             :                         }
    7080             :                     } else {
    7081           0 :                         --SurfNum;
    7082             :                     }
    7083             :                 }
    7084             :             }
    7085             :         }
    7086         796 :     }
    7087             : 
    7088         796 :     void GetIntMassSurfaceData(EnergyPlusData &state,
    7089             :                                bool &ErrorsFound, // Error flag indicator (true if errors found)
    7090             :                                int &SurfNum       // Count of Current SurfaceNumber
    7091             :     )
    7092             :     {
    7093             : 
    7094             :         // SUBROUTINE INFORMATION:
    7095             :         //       AUTHOR         Linda Lawrie
    7096             :         //       DATE WRITTEN   May 2000
    7097             :         //       MODIFIED       na
    7098             :         //       RE-ENGINEERED  na
    7099             : 
    7100             :         // PURPOSE OF THIS SUBROUTINE:
    7101             :         // This subroutine gets the Internal Surface Data,
    7102             :         // checks it for errors, etc.
    7103             : 
    7104             :         // METHODOLOGY EMPLOYED:
    7105             :         // na
    7106             : 
    7107             :         // REFERENCES:
    7108             :         // Internal Mass Surface Definition
    7109             :         // Surface:HeatTransfer:InternalMass,
    7110             :         //       \note used to describe internal zone surface area that does not need to be part of geometric representation
    7111             :         //  A1 , \field User Supplied Surface Name
    7112             :         //       \type alpha
    7113             :         //       \reference SurfaceNames
    7114             :         //  A2 , \field Construction Name of the Surface
    7115             :         //       \note To be matched with a construction in this input file
    7116             :         //       \type object-list
    7117             :         //       \object-list ConstructionNames
    7118             :         //  A3 , \field Interior Environment
    7119             :         //       \note Zone the surface is a part of
    7120             :         //       \type object-list
    7121             :         //       \object-list ZoneNames
    7122             :         //  N1,  \field View factor to Person (to people?)
    7123             :         //       \type real
    7124             :         //       \note from the interior of the surface
    7125             :         //  N2 ; \field Surface area
    7126             :         //       \units m2
    7127             : 
    7128             :         // Using/Aliasing
    7129             :         using namespace Vectors;
    7130             :         using General::CheckCreatedZoneItemName;
    7131             : 
    7132             :         // SUBROUTINE PARAMETER DEFINITIONS:
    7133             :         static constexpr std::string_view RoutineName("GetIntMassSurfaceData: ");
    7134             : 
    7135             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7136             :         int IOStat;                // IO Status when calling get input subroutine
    7137             :         int SurfaceNumAlpha;       // Number of material alpha names being passed
    7138             :         int SurfaceNumArg;         // Number of material properties being passed
    7139             :         int ZoneNum;               // index to a zone
    7140         796 :         int NumIntMassSurfaces(0); // total count of internal mass surfaces
    7141             :         bool errFlag;              //  local error flag
    7142         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7143         796 :         cCurrentModuleObject = "InternalMass";
    7144         796 :         int TotIntMass = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7145         796 :         if (TotIntMass == 0) return;
    7146             : 
    7147         170 :         state.dataSurface->IntMassObjects.allocate(TotIntMass);
    7148             : 
    7149             :         // scan for use of Zone lists in InternalMass objects
    7150         170 :         errFlag = false;
    7151         170 :         NumIntMassSurfaces = 0;
    7152        2555 :         for (int Item = 1; Item <= TotIntMass; ++Item) {
    7153        4770 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7154             :                                                                      cCurrentModuleObject,
    7155             :                                                                      Item,
    7156        2385 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7157             :                                                                      SurfaceNumAlpha,
    7158        2385 :                                                                      state.dataIPShortCut->rNumericArgs,
    7159             :                                                                      SurfaceNumArg,
    7160             :                                                                      IOStat,
    7161        2385 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7162        2385 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7163        2385 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7164        2385 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7165             : 
    7166        4770 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    7167        2385 :                                                          state.dataSurfaceGeometry->UniqueSurfaceNames,
    7168        2385 :                                                          state.dataIPShortCut->cAlphaArgs(1),
    7169             :                                                          cCurrentModuleObject,
    7170        2385 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    7171             :                                                          ErrorsFound)) {
    7172           0 :                 continue;
    7173             :             }
    7174             : 
    7175        2385 :             state.dataSurface->IntMassObjects(Item).Name = state.dataIPShortCut->cAlphaArgs(1);
    7176        2385 :             state.dataSurface->IntMassObjects(Item).GrossArea = state.dataIPShortCut->rNumericArgs(1);
    7177        2385 :             state.dataSurface->IntMassObjects(Item).Construction =
    7178        2385 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    7179        2385 :             state.dataSurface->IntMassObjects(Item).ZoneOrZoneListName = state.dataIPShortCut->cAlphaArgs(3);
    7180        2385 :             int Item1 = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    7181        2385 :             int ZLItem = 0;
    7182        2385 :             if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0)
    7183           5 :                 ZLItem = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->ZoneList);
    7184        2385 :             if (Item1 > 0) {
    7185        2380 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7186        2380 :                     ++NumIntMassSurfaces;
    7187             :                 }
    7188        2380 :                 state.dataSurface->IntMassObjects(Item).NumOfZones = 1;
    7189        2380 :                 state.dataSurface->IntMassObjects(Item).ZoneListActive = false;
    7190        2380 :                 state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = Item1;
    7191           5 :             } else if (ZLItem > 0) {
    7192           2 :                 NumIntMassSurfaces += state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
    7193           2 :                 state.dataSurface->IntMassObjects(Item).NumOfZones = state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
    7194           2 :                 state.dataSurface->IntMassObjects(Item).ZoneListActive = true;
    7195           2 :                 state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = ZLItem;
    7196           3 :             } else if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7197             :                 // If Space or SpaceList Name is blank, then throw error.
    7198           0 :                 ShowSevereError(state,
    7199           0 :                                 format("{}=\"{}\" invalid {}=\"{}\" not found.",
    7200             :                                        cCurrentModuleObject,
    7201           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    7202           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    7203           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
    7204           0 :                 ++SurfNum;
    7205           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    7206           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
    7207           0 :                 ErrorsFound = true;
    7208           0 :                 errFlag = true;
    7209             :             }
    7210             : 
    7211        2385 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7212           3 :                 state.dataSurface->IntMassObjects(Item).spaceOrSpaceListName = state.dataIPShortCut->cAlphaArgs(4);
    7213           3 :                 int Item1 = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
    7214           3 :                 int SLItem = 0;
    7215           3 :                 if (Item1 == 0 && int(state.dataHeatBal->spaceList.size()) > 0)
    7216           1 :                     SLItem = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->spaceList);
    7217           3 :                 if (Item1 > 0) {
    7218           2 :                     ++NumIntMassSurfaces;
    7219           2 :                     state.dataSurface->IntMassObjects(Item).numOfSpaces = 1;
    7220           2 :                     state.dataSurface->IntMassObjects(Item).spaceListActive = false;
    7221           2 :                     state.dataSurface->IntMassObjects(Item).spaceOrSpaceListPtr = Item1;
    7222           2 :                     state.dataSurface->IntMassObjects(Item).NumOfZones = 1;
    7223           2 :                     state.dataSurface->IntMassObjects(Item).ZoneListActive = false;
    7224           2 :                     state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = state.dataHeatBal->space(Item1).zoneNum;
    7225           1 :                 } else if (SLItem > 0) {
    7226           1 :                     int numOfSpaces = int(state.dataHeatBal->spaceList(SLItem).numListSpaces);
    7227           1 :                     NumIntMassSurfaces += numOfSpaces;
    7228           1 :                     state.dataSurface->IntMassObjects(Item).numOfSpaces = numOfSpaces;
    7229           1 :                     state.dataSurface->IntMassObjects(Item).spaceListActive = true;
    7230           1 :                     state.dataSurface->IntMassObjects(Item).spaceOrSpaceListPtr = SLItem;
    7231             :                 } else {
    7232           0 :                     ShowSevereError(state,
    7233           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
    7234             :                                            cCurrentModuleObject,
    7235           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    7236           0 :                                            state.dataIPShortCut->cAlphaFieldNames(4),
    7237           0 :                                            state.dataIPShortCut->cAlphaArgs(4)));
    7238           0 :                     ++SurfNum;
    7239           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
    7240           0 :                     ErrorsFound = true;
    7241           0 :                     errFlag = true;
    7242             :                 }
    7243             :             }
    7244             : 
    7245        2385 :             if (errFlag) {
    7246           0 :                 ShowSevereError(state, format("{}Errors with invalid names in {} objects.", RoutineName, cCurrentModuleObject));
    7247           0 :                 ShowContinueError(state, "...These will not be read in.  Other errors may occur.");
    7248           0 :                 NumIntMassSurfaces = 0;
    7249             :             }
    7250             : 
    7251        2385 :             if (state.dataSurface->IntMassObjects(Item).Construction == 0) {
    7252           0 :                 ErrorsFound = true;
    7253           0 :                 ShowSevereError(state,
    7254           0 :                                 format("{}=\"{}\", {} not found={}",
    7255             :                                        cCurrentModuleObject,
    7256           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    7257           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    7258           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    7259        2385 :             } else if (state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Item).Construction).TypeIsWindow) {
    7260           0 :                 ErrorsFound = true;
    7261           0 :                 ShowSevereError(state,
    7262           0 :                                 format("{}=\"{}\", invalid {}=\"{}\" - has Window materials.",
    7263             :                                        cCurrentModuleObject,
    7264           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    7265           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    7266           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    7267             :             } else {
    7268        2385 :                 state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Item).Construction).IsUsed = true;
    7269             :             }
    7270             :         }
    7271             : 
    7272         170 :         if (NumIntMassSurfaces > 0) {
    7273         170 :             int spaceNum = 0;
    7274        2555 :             for (int Loop = 1; Loop <= TotIntMass; ++Loop) {
    7275        2385 :                 int numberOfZonesOrSpaces = 1;
    7276        2385 :                 if (state.dataSurface->IntMassObjects(Loop).ZoneListActive) {
    7277           2 :                     numberOfZonesOrSpaces = state.dataSurface->IntMassObjects(Loop).NumOfZones;
    7278        2383 :                 } else if (state.dataSurface->IntMassObjects(Loop).spaceListActive) {
    7279           1 :                     numberOfZonesOrSpaces = state.dataSurface->IntMassObjects(Loop).numOfSpaces;
    7280             :                 }
    7281             : 
    7282        4783 :                 for (int Item1 = 1; Item1 <= numberOfZonesOrSpaces; ++Item1) {
    7283             : 
    7284        2398 :                     ++SurfNum;
    7285             : 
    7286        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = state.dataSurface->IntMassObjects(Loop).Construction;
    7287        2398 :                     if (!state.dataSurface->IntMassObjects(Loop).ZoneListActive && !state.dataSurface->IntMassObjects(Loop).spaceListActive) {
    7288        2382 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr;
    7289        2382 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = state.dataSurface->IntMassObjects(Loop).spaceOrSpaceListPtr;
    7290        2382 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataSurface->IntMassObjects(Loop).Name;
    7291        2382 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::IntMass;
    7292        2382 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListName;
    7293        2382 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    7294             :                     } else {
    7295          16 :                         if (state.dataSurface->IntMassObjects(Loop).ZoneListActive) {
    7296          24 :                             CheckCreatedZoneItemName(
    7297             :                                 state,
    7298             :                                 RoutineName,
    7299             :                                 cCurrentModuleObject,
    7300             :                                 state.dataHeatBal
    7301           8 :                                     ->Zone(state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).Zone(Item1))
    7302           8 :                                     .Name,
    7303           8 :                                 state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).MaxZoneNameLength,
    7304           8 :                                 state.dataSurface->IntMassObjects(Loop).Name,
    7305           8 :                                 state.dataSurfaceGeometry->SurfaceTmp,
    7306           8 :                                 SurfNum - 1,
    7307           8 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    7308             :                                 errFlag);
    7309             : 
    7310           8 :                             ZoneNum = state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).Zone(Item1);
    7311           8 :                         } else if (state.dataSurface->IntMassObjects(Loop).spaceListActive) {
    7312           8 :                             spaceNum = state.dataHeatBal->spaceList(state.dataSurface->IntMassObjects(Loop).spaceOrSpaceListPtr).spaces(Item1);
    7313           8 :                             ZoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
    7314           8 :                             const std::string spaceName = state.dataHeatBal->space(spaceNum).Name;
    7315           8 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = spaceName + ' ' + state.dataSurface->IntMassObjects(Loop).Name;
    7316           8 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
    7317           8 :                         }
    7318          16 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
    7319          16 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::IntMass;
    7320          16 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataHeatBal->Zone(ZoneNum).Name;
    7321          16 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
    7322          16 :                         if (errFlag) ErrorsFound = true;
    7323             :                     }
    7324             : 
    7325        2398 :                     if (state.dataSurface->IntMassObjects(Loop).Construction > 0) {
    7326        2398 :                         if (state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Loop).Construction).IsUsed) {
    7327        2398 :                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
    7328        2398 :                                 state.dataSurface->IntMassObjects(Loop).Construction;
    7329             :                         }
    7330             :                     }
    7331        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = state.dataSurface->IntMassObjects(Loop).GrossArea;
    7332        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    7333        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    7334        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    7335        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = 1.0;
    7336        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = 90.0;
    7337        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    7338        2398 :                         Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    7339        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = 0.0; // Tuned Was std::cos( 90.0 * DegToRadians )
    7340        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = 1.0; // Tuned Was std::sin( 90.0 * DegToRadians )
    7341        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = 0.0;
    7342        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = 1.0; // Tuned Was std::cos( 0.0 )
    7343        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = 0.0; // Tuned Was std::sin( 0.0 )
    7344             :                     // Outward normal unit vector (pointing away from room)
    7345        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz;
    7346        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5;
    7347        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
    7348        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
    7349        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
    7350        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    7351        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
    7352        2398 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
    7353             :                 }
    7354             :             }
    7355             :         }
    7356             :     }
    7357             : 
    7358         796 :     int GetNumIntMassSurfaces(EnergyPlusData &state) // Number of Internal Mass Surfaces to obtain
    7359             : 
    7360             :     {
    7361             :         // Counts internal mass surfaces applied to zones and zone lists
    7362             : 
    7363             :         // Using/Aliasing
    7364             : 
    7365             :         int IOStat;          // IO Status when calling get input subroutine
    7366             :         int SurfaceNumAlpha; // Number of material alpha names being passed
    7367             :         int SurfaceNumArg;   // Number of material properties being passed
    7368             :         int NumIntMassSurf;  // total count of internal mass surfaces
    7369             : 
    7370         796 :         NumIntMassSurf = 0;
    7371         796 :         int TotIntMass = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "InternalMass");
    7372             : 
    7373         796 :         if (TotIntMass == 0) return NumIntMassSurf;
    7374         170 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7375         170 :         cCurrentModuleObject = "InternalMass";
    7376             :         // scan for zones and zone lists in InternalMass objects
    7377        2555 :         for (int Item = 1; Item <= TotIntMass; ++Item) {
    7378        4770 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7379             :                                                                      cCurrentModuleObject,
    7380             :                                                                      Item,
    7381        2385 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7382             :                                                                      SurfaceNumAlpha,
    7383        2385 :                                                                      state.dataIPShortCut->rNumericArgs,
    7384             :                                                                      SurfaceNumArg,
    7385             :                                                                      IOStat,
    7386        2385 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7387        2385 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7388        2385 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7389        2385 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7390             : 
    7391        2385 :             int Item1 = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
    7392        2385 :             int ZLItem = 0;
    7393        2385 :             if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0)
    7394           5 :                 ZLItem = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->ZoneList);
    7395        2385 :             if (Item1 > 0) {
    7396        2380 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7397        2380 :                     ++NumIntMassSurf;
    7398             :                 }
    7399           5 :             } else if (ZLItem > 0) {
    7400           2 :                 NumIntMassSurf += state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
    7401             :             }
    7402             : 
    7403        2385 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    7404           3 :                 int Item1 = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
    7405           3 :                 int SLItem = 0;
    7406           3 :                 if (Item1 == 0 && int(state.dataHeatBal->spaceList.size()) > 0)
    7407           1 :                     SLItem = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->spaceList);
    7408           3 :                 if (Item1 > 0) {
    7409           2 :                     ++NumIntMassSurf;
    7410           1 :                 } else if (SLItem > 0) {
    7411           1 :                     int numOfSpaces = int(state.dataHeatBal->spaceList(SLItem).numListSpaces);
    7412           1 :                     NumIntMassSurf += numOfSpaces;
    7413             :                 }
    7414             :             }
    7415             :         }
    7416         170 :         NumIntMassSurf = max(NumIntMassSurf, TotIntMass);
    7417         170 :         return NumIntMassSurf;
    7418             :     }
    7419             : 
    7420           9 :     void GetShadingSurfReflectanceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    7421             :     {
    7422             : 
    7423             :         // SUBROUTINE INFORMATION:
    7424             :         //       AUTHOR         Fred Winkelmann
    7425             :         //       DATE WRITTEN   Sept 2003
    7426             :         //       MODIFIED       na
    7427             :         //       RE-ENGINEERED  na
    7428             : 
    7429             :         // PURPOSE OF THIS SUBROUTINE:
    7430             :         // Gets data for a Shading Surface Reflectance object.  This is only called when the
    7431             :         // Solar Distribution is to be calculated for reflectances.
    7432             : 
    7433             :         // Using/Aliasing
    7434             : 
    7435             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7436             : 
    7437             :         int IOStat;                       // IO Status when calling get input subroutine
    7438             :         int NumAlpha;                     // Number of alpha names being passed
    7439             :         int NumProp;                      // Number of properties being passed
    7440             :         int TotShadingSurfaceReflectance; // Total Shading Surface Refleftance statements
    7441             :         int Loop;                         // DO loop index
    7442             :         int SurfNum;                      // Surface number
    7443             :         int GlConstrNum;                  // Glazing construction number
    7444             :         bool WrongSurfaceType;
    7445             : 
    7446             :         // For shading surfaces, initialize value of reflectance values to default values. These values
    7447             :         // may be overridden below for shading surfaces with an associated Shading Surface Reflectance object.
    7448         101 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    7449          92 :             auto const &surf = state.dataSurface->Surface(SurfNum);
    7450          92 :             if (!(surf.Class == SurfaceClass::Shading || surf.Class == SurfaceClass::Detached_F || surf.Class == SurfaceClass::Detached_B ||
    7451          86 :                   surf.Class == SurfaceClass::Overhang || surf.Class == SurfaceClass::Fin))
    7452          86 :                 continue;
    7453           6 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) = 0.2;
    7454           6 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) = 0.2;
    7455           6 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = 0.0;
    7456           6 :             state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = 0;
    7457             :         }
    7458             : 
    7459             :         // Get the total number of Shading Surface Reflectance objects
    7460           9 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7461           9 :         cCurrentModuleObject = "ShadingProperty:Reflectance";
    7462           9 :         TotShadingSurfaceReflectance = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7463             :         //  IF(TotShadingSurfaceReflectance.EQ.0) RETURN
    7464             : 
    7465          10 :         for (Loop = 1; Loop <= TotShadingSurfaceReflectance; ++Loop) {
    7466             : 
    7467           2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7468             :                                                                      cCurrentModuleObject,
    7469             :                                                                      Loop,
    7470           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7471             :                                                                      NumAlpha,
    7472           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    7473             :                                                                      NumProp,
    7474             :                                                                      IOStat,
    7475           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7476           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7477           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7478           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7479           1 :             SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7480           1 :             if (SurfNum == 0) {
    7481           0 :                 ShowWarningError(state, format("{}=\"{}\", invalid specification", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    7482           0 :                 ShowContinueError(state,
    7483           0 :                                   format(".. not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(1), state.dataIPShortCut->cAlphaArgs(1)));
    7484             :                 //      ErrorsFound =.TRUE.
    7485           0 :                 continue;
    7486             :             }
    7487             : 
    7488             :             // Check that associated surface is a shading surface
    7489           1 :             WrongSurfaceType = false;
    7490           1 :             if (SurfNum != 0) {
    7491           1 :                 auto const &surf = state.dataSurface->Surface(SurfNum);
    7492           1 :                 if (!(surf.Class == SurfaceClass::Shading || surf.Class == SurfaceClass::Detached_F || surf.Class == SurfaceClass::Detached_B ||
    7493           0 :                       surf.Class == SurfaceClass::Overhang || surf.Class == SurfaceClass::Fin))
    7494           0 :                     WrongSurfaceType = true;
    7495           1 :                 if (WrongSurfaceType) {
    7496           0 :                     ShowSevereError(
    7497             :                         state,
    7498           0 :                         format("GetShadingSurfReflectanceData: {}=\"{}\", surface is not a shading surface.", cCurrentModuleObject, surf.Name));
    7499           0 :                     ErrorsFound = true;
    7500           0 :                     continue;
    7501             :                 }
    7502             :             }
    7503             : 
    7504             :             // If associated surface is a shading surface, set reflectance values
    7505           1 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = state.dataIPShortCut->rNumericArgs(3);
    7506           1 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) =
    7507           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(1);
    7508           1 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) =
    7509           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(2);
    7510           1 :             if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    7511             :                 GlConstrNum =
    7512           1 :                     Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    7513           1 :                 if (GlConstrNum == 0) {
    7514           0 :                     ShowSevereError(state,
    7515           0 :                                     format("{}=\"{}\", {} not found={}",
    7516             :                                            cCurrentModuleObject,
    7517           0 :                                            state.dataSurface->Surface(SurfNum).Name,
    7518           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    7519           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    7520           0 :                     ErrorsFound = true;
    7521             :                 } else {
    7522           1 :                     state.dataConstruction->Construct(GlConstrNum).IsUsed = true;
    7523             :                 }
    7524           1 :                 state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = GlConstrNum;
    7525             :             }
    7526           1 :             SurfNum = Util::FindItemInList("Mir-" + state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7527           1 :             if (SurfNum == 0) continue;
    7528           1 :             state.dataSurface->SurfShadowGlazingFrac(SurfNum) = state.dataIPShortCut->rNumericArgs(3);
    7529           1 :             state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) =
    7530           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(1);
    7531           1 :             state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) =
    7532           1 :                 (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(2);
    7533           1 :             if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
    7534             :                 GlConstrNum =
    7535           1 :                     Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    7536           1 :                 if (GlConstrNum != 0) {
    7537           1 :                     state.dataConstruction->Construct(GlConstrNum).IsUsed = true;
    7538             :                 }
    7539           1 :                 state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = GlConstrNum;
    7540             :             }
    7541             : 
    7542             :         } // End of loop over Shading Surface Reflectance objects
    7543             : 
    7544             :         // Write reflectance values to .eio file.
    7545           9 :         print(state.files.eio,
    7546             :               "! <ShadingProperty Reflectance>,Shading Surface Name,Shading Type,Diffuse Solar Reflectance, Diffuse "
    7547             :               "Visible Reflectance,Surface Glazing Fraction,Surface Glazing Contruction\n");
    7548             : 
    7549         101 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    7550          92 :             auto const &surf = state.dataSurface->Surface(SurfNum);
    7551          92 :             if (!(surf.Class == SurfaceClass::Shading || surf.Class == SurfaceClass::Detached_F || surf.Class == SurfaceClass::Detached_B ||
    7552          86 :                   surf.Class == SurfaceClass::Overhang || surf.Class == SurfaceClass::Fin))
    7553          86 :                 continue;
    7554             : 
    7555           6 :             constexpr std::string_view fmt = "ShadingProperty Reflectance,{},{},{:.2R},{:.2R},{:.2R}, {}\n";
    7556           6 :             if (state.dataSurface->SurfShadowGlazingConstruct(SurfNum) != 0) {
    7557           6 :                 print(state.files.eio,
    7558             :                       fmt,
    7559           2 :                       surf.Name,
    7560           4 :                       cSurfaceClass(surf.Class),
    7561           2 :                       state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum),
    7562           2 :                       state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum),
    7563           2 :                       state.dataSurface->SurfShadowGlazingFrac(SurfNum),
    7564           2 :                       state.dataConstruction->Construct(state.dataSurface->SurfShadowGlazingConstruct(SurfNum)).Name);
    7565             :             } else {
    7566          12 :                 print(state.files.eio,
    7567             :                       fmt,
    7568           4 :                       surf.Name,
    7569           8 :                       cSurfaceClass(surf.Class),
    7570           4 :                       state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum),
    7571           4 :                       state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum),
    7572           4 :                       state.dataSurface->SurfShadowGlazingFrac(SurfNum),
    7573             :                       "N/A");
    7574             :             }
    7575             :         }
    7576           9 :     }
    7577             : 
    7578         796 :     void GetHTSurfExtVentedCavityData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    7579             :     {
    7580             : 
    7581             :         // SUBROUTINE INFORMATION:
    7582             :         //       AUTHOR         BGriffith
    7583             :         //       DATE WRITTEN   January 2005
    7584             :         //       MODIFIED       na
    7585             :         //       RE-ENGINEERED  na
    7586             : 
    7587             :         // PURPOSE OF THIS SUBROUTINE:
    7588             :         // load input data for Exterior Vented Cavity Special case for heat transfer surfaces
    7589             : 
    7590             :         // METHODOLOGY EMPLOYED:
    7591             :         // usual E+ input processes
    7592             : 
    7593             :         // REFERENCES:
    7594             :         // derived from SUBROUTINE GetTranspiredCollectorInput
    7595             : 
    7596             :         // Using/Aliasing
    7597             : 
    7598             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    7599             : 
    7600             :         int Item;          // Item to be "gotten"
    7601             :         int NumAlphas;     // Number of Alphas for each GetObjectItem call
    7602             :         int NumNumbers;    // Number of Numbers for each GetObjectItem call
    7603             :         int MaxNumAlphas;  // argument for call to GetObjectDefMaxArgs
    7604             :         int MaxNumNumbers; // argument for call to GetObjectDefMaxArgs
    7605             :         int Dummy;         // argument for call to GetObjectDefMaxArgs
    7606             :         int IOStatus;      // Used in GetObjectItem
    7607             :         int Found;
    7608             :         int AlphaOffset; // local temp var
    7609         796 :         std::string Roughness;
    7610             :         int ThisSurf;                   // do loop counter
    7611             :         Real64 AvgAzimuth;              // temp for error checking
    7612             :         Real64 AvgTilt;                 // temp for error checking
    7613         796 :         constexpr Real64 AZITOL = 15.0; // Degree Azimuth Angle Tolerance
    7614         796 :         constexpr Real64 TILTOL = 10.0; // Degree Tilt Angle Tolerance
    7615             :         int SurfID;                     // local surface "pointer"
    7616             :         bool IsBlank;
    7617             :         bool ErrorInName;
    7618         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    7619         796 :         cCurrentModuleObject = "SurfaceProperty:ExteriorNaturalVentedCavity";
    7620         796 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Dummy, MaxNumAlphas, MaxNumNumbers);
    7621             : 
    7622         796 :         if (MaxNumNumbers != 8) {
    7623           0 :             ShowSevereError(
    7624           0 :                 state, format("{}: Object Definition indicates not = 8 Number Objects, Number Indicated={}", cCurrentModuleObject, MaxNumNumbers));
    7625           0 :             ErrorsFound = true;
    7626             :         }
    7627             : 
    7628         796 :         state.dataSurface->TotExtVentCav = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7629             : 
    7630         796 :         state.dataHeatBal->ExtVentedCavity.allocate(state.dataSurface->TotExtVentCav);
    7631             : 
    7632         801 :         for (Item = 1; Item <= state.dataSurface->TotExtVentCav; ++Item) {
    7633          10 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7634             :                                                                      cCurrentModuleObject,
    7635             :                                                                      Item,
    7636           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7637             :                                                                      NumAlphas,
    7638           5 :                                                                      state.dataIPShortCut->rNumericArgs,
    7639             :                                                                      NumNumbers,
    7640             :                                                                      IOStatus,
    7641           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7642           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7643           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7644           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7645             :             // first handle cAlphaArgs
    7646           5 :             ErrorInName = false;
    7647           5 :             IsBlank = false;
    7648             : 
    7649          10 :             Util::VerifyName(state,
    7650           5 :                              state.dataIPShortCut->cAlphaArgs(1),
    7651           5 :                              state.dataHeatBal->ExtVentedCavity,
    7652             :                              Item - 1,
    7653             :                              ErrorInName,
    7654             :                              IsBlank,
    7655          10 :                              cCurrentModuleObject + " Name");
    7656           5 :             if (ErrorInName) {
    7657           0 :                 ShowContinueError(state, "...cannot not duplicate other names");
    7658           0 :                 ErrorsFound = true;
    7659           0 :                 continue;
    7660             :             }
    7661           5 :             state.dataHeatBal->ExtVentedCavity(Item).Name = state.dataIPShortCut->cAlphaArgs(1);
    7662             : 
    7663           5 :             state.dataHeatBal->ExtVentedCavity(Item).OSCMName = state.dataIPShortCut->cAlphaArgs(2);
    7664           5 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    7665           5 :                 Found = Util::FindItemInList(state.dataHeatBal->ExtVentedCavity(Item).OSCMName, state.dataSurface->OSCM, state.dataSurface->TotOSCM);
    7666           5 :                 if (Found == 0) {
    7667           0 :                     ShowSevereError(state,
    7668           0 :                                     format("{}=\"{}\", invalid {}=\"{}\".",
    7669             :                                            cCurrentModuleObject,
    7670           0 :                                            state.dataHeatBal->ExtVentedCavity(Item).Name,
    7671           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    7672           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    7673           0 :                     ErrorsFound = true;
    7674             :                 }
    7675             :             } else {
    7676           0 :                 Found = 0;
    7677           0 :                 ShowSevereError(state,
    7678           0 :                                 format("{}=\"{}\", invalid {} cannot be blank.",
    7679             :                                        cCurrentModuleObject,
    7680           0 :                                        state.dataHeatBal->ExtVentedCavity(Item).Name,
    7681           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2)));
    7682           0 :                 ErrorsFound = true;
    7683             :             }
    7684           5 :             state.dataHeatBal->ExtVentedCavity(Item).OSCMPtr = Found;
    7685             : 
    7686           5 :             Roughness = state.dataIPShortCut->cAlphaArgs(3);
    7687             :             // Select the correct Number for the associated ascii name for the roughness type
    7688           5 :             if (Util::SameString(Roughness, "VerySmooth")) {
    7689           0 :                 state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness = Material::SurfaceRoughness::VerySmooth;
    7690           5 :             } else if (Util::SameString(Roughness, "Smooth")) {
    7691           5 :                 state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness = Material::SurfaceRoughness::Smooth;
    7692           0 :             } else if (Util::SameString(Roughness, "MediumSmooth")) {
    7693           0 :                 state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness = Material::SurfaceRoughness::MediumSmooth;
    7694           0 :             } else if (Util::SameString(Roughness, "MediumRough")) {
    7695           0 :                 state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness = Material::SurfaceRoughness::MediumRough;
    7696           0 :             } else if (Util::SameString(Roughness, "Rough")) {
    7697           0 :                 state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness = Material::SurfaceRoughness::Rough;
    7698           0 :             } else if (Util::SameString(Roughness, "VeryRough")) {
    7699           0 :                 state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness = Material::SurfaceRoughness::VeryRough;
    7700             :             } // TODO: fix this after creating FindEnumeratedValueIndex()
    7701             : 
    7702             :             // Was it set?
    7703           5 :             if (state.dataHeatBal->ExtVentedCavity(Item).BaffleRoughness == Material::SurfaceRoughness::Invalid) {
    7704           0 :                 ShowSevereError(state,
    7705           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    7706             :                                        cCurrentModuleObject,
    7707           0 :                                        state.dataHeatBal->ExtVentedCavity(Item).Name,
    7708           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    7709           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
    7710           0 :                 ErrorsFound = true;
    7711             :             }
    7712             : 
    7713           5 :             AlphaOffset = 3;
    7714           5 :             state.dataHeatBal->ExtVentedCavity(Item).NumSurfs = NumAlphas - AlphaOffset;
    7715           5 :             if (state.dataHeatBal->ExtVentedCavity(Item).NumSurfs == 0) {
    7716           0 :                 ShowSevereError(state,
    7717           0 :                                 format("{}=\"{}\", no underlying surfaces specified. Must have at least one.",
    7718             :                                        cCurrentModuleObject,
    7719           0 :                                        state.dataHeatBal->ExtVentedCavity(Item).Name));
    7720           0 :                 ErrorsFound = true;
    7721           0 :                 continue;
    7722             :             }
    7723           5 :             state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs.allocate(state.dataHeatBal->ExtVentedCavity(Item).NumSurfs);
    7724           5 :             state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs = 0;
    7725          10 :             for (ThisSurf = 1; ThisSurf <= state.dataHeatBal->ExtVentedCavity(Item).NumSurfs; ++ThisSurf) {
    7726           5 :                 Found = Util::FindItemInList(
    7727           5 :                     state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7728           5 :                 if (Found == 0) {
    7729           0 :                     ShowSevereError(state,
    7730           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    7731             :                                            cCurrentModuleObject,
    7732           0 :                                            state.dataHeatBal->ExtVentedCavity(Item).Name,
    7733           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset),
    7734           0 :                                            state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset)));
    7735           0 :                     ErrorsFound = true;
    7736           0 :                     continue;
    7737             :                 }
    7738             :                 // check that surface is appropriate, Heat transfer, Sun, Wind,
    7739           5 :                 if (!state.dataSurface->Surface(Found).HeatTransSurf) {
    7740           0 :                     ShowSevereError(state,
    7741           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    7742             :                                            cCurrentModuleObject,
    7743           0 :                                            state.dataHeatBal->ExtVentedCavity(Item).Name,
    7744           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset),
    7745           0 :                                            state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset)));
    7746           0 :                     ShowContinueError(state, "...because it is not a Heat Transfer Surface.");
    7747           0 :                     ErrorsFound = true;
    7748           0 :                     continue;
    7749             :                 }
    7750           5 :                 if (!state.dataSurface->Surface(Found).ExtSolar) {
    7751           0 :                     ShowSevereError(state,
    7752           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    7753             :                                            cCurrentModuleObject,
    7754           0 :                                            state.dataHeatBal->ExtVentedCavity(Item).Name,
    7755           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset),
    7756           0 :                                            state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset)));
    7757           0 :                     ShowContinueError(state, "...because it is not exposed to Sun.");
    7758           0 :                     ErrorsFound = true;
    7759           0 :                     continue;
    7760             :                 }
    7761           5 :                 if (!state.dataSurface->Surface(Found).ExtWind) {
    7762           0 :                     ShowSevereError(state,
    7763           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    7764             :                                            cCurrentModuleObject,
    7765           0 :                                            state.dataHeatBal->ExtVentedCavity(Item).Name,
    7766           0 :                                            state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset),
    7767           0 :                                            state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset)));
    7768           0 :                     ShowContinueError(state, "...because it is not exposed to Wind.");
    7769           0 :                     ErrorsFound = true;
    7770           0 :                     continue;
    7771             :                 }
    7772           5 :                 if (state.dataSurface->Surface(Found).ExtBoundCond != OtherSideCondModeledExt) {
    7773           0 :                     ShowSevereError(state, format("{}=\"{}\", is invalid", cCurrentModuleObject, state.dataHeatBal->ExtVentedCavity(Item).Name));
    7774           0 :                     ShowContinueError(state,
    7775           0 :                                       format("...because {}=\"{}\".",
    7776           0 :                                              state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset),
    7777           0 :                                              state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset)));
    7778           0 :                     ShowContinueError(state, "...is not an OtherSideConditionedModel surface.");
    7779           0 :                     ErrorsFound = true;
    7780           0 :                     continue;
    7781             :                 }
    7782           5 :                 state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs(ThisSurf) = Found;
    7783             : 
    7784             :                 // now set info in Surface structure
    7785           5 :                 state.dataSurface->SurfExtCavNum(Found) = Item;
    7786           5 :                 state.dataSurface->SurfExtCavityPresent(Found) = true;
    7787             :             }
    7788             : 
    7789           5 :             if (ErrorsFound) continue; // previous inner do loop may have detected problems that need to be cycle'd again to avoid crash
    7790             : 
    7791             :             // now that we should have all the surfaces, do some preperations and checks.
    7792             : 
    7793             :             // are they all similar tilt and azimuth? Issue warnings so people can do it if they really want
    7794           5 :             Real64 const surfaceArea(sum_sub(state.dataSurface->Surface, &SurfaceData::Area, state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs));
    7795             :             //            AvgAzimuth = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Azimuth * Surface( ExtVentedCavity( Item ).SurfPtrs
    7796             :             //).Area
    7797             :             //)
    7798             :             ///  sum(  Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
    7799           5 :             AvgAzimuth = sum_product_sub(state.dataSurface->Surface,
    7800             :                                          &SurfaceData::Azimuth,
    7801             :                                          &SurfaceData::Area,
    7802           5 :                                          state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs) /
    7803             :                          surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
    7804             :             //            AvgTilt = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Tilt * Surface( ExtVentedCavity( Item ).SurfPtrs ).Area )
    7805             :             //            /
    7806             :             // sum(  Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
    7807          10 :             AvgTilt = sum_product_sub(
    7808           5 :                           state.dataSurface->Surface, &SurfaceData::Tilt, &SurfaceData::Area, state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs) /
    7809             :                       surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
    7810          10 :             for (ThisSurf = 1; ThisSurf <= state.dataHeatBal->ExtVentedCavity(Item).NumSurfs; ++ThisSurf) {
    7811           5 :                 SurfID = state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs(ThisSurf);
    7812           5 :                 if (General::rotAzmDiffDeg(state.dataSurface->Surface(SurfID).Azimuth, AvgAzimuth) > AZITOL) {
    7813           0 :                     ShowWarningError(state,
    7814           0 :                                      format("{}=\"{}, Surface {} has Azimuth different from others in the associated group.",
    7815             :                                             cCurrentModuleObject,
    7816           0 :                                             state.dataHeatBal->ExtVentedCavity(Item).Name,
    7817           0 :                                             state.dataSurface->Surface(SurfID).Name));
    7818             :                 }
    7819           5 :                 if (std::abs(state.dataSurface->Surface(SurfID).Tilt - AvgTilt) > TILTOL) {
    7820           0 :                     ShowWarningError(state,
    7821           0 :                                      format("{}=\"{}, Surface {} has Tilt different from others in the associated group.",
    7822             :                                             cCurrentModuleObject,
    7823           0 :                                             state.dataHeatBal->ExtVentedCavity(Item).Name,
    7824           0 :                                             state.dataSurface->Surface(SurfID).Name));
    7825             :                 }
    7826             : 
    7827             :                 // test that there are no windows.  Now allow windows
    7828             :                 // If (Surface(SurfID)%GrossArea >  Surface(SurfID)%Area) Then
    7829             :                 //      Call ShowWarningError(state, 'Surface '//TRIM(Surface(SurfID)%name)//' has a subsurface whose area is not being ' &
    7830             :                 //         //'subtracted in the group of surfaces associated with '//TRIM(ExtVentedCavity(Item)%Name))
    7831             :                 // endif
    7832             :             }
    7833           5 :             state.dataHeatBal->ExtVentedCavity(Item).Tilt = AvgTilt;
    7834           5 :             state.dataHeatBal->ExtVentedCavity(Item).Azimuth = AvgAzimuth;
    7835             : 
    7836             :             // find area weighted centroid.
    7837             :             //            ExtVentedCavity( Item ).Centroid.z = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Centroid.z * Surface(
    7838             :             // ExtVentedCavity(  Item
    7839             :             //).SurfPtrs ).Area ) / sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced
    7840             :             // by below
    7841          10 :             state.dataHeatBal->ExtVentedCavity(Item).Centroid.z = sum_product_sub(state.dataSurface->Surface,
    7842             :                                                                                   &SurfaceData::Centroid,
    7843             :                                                                                   &Vector::z,
    7844           5 :                                                                                   state.dataSurface->Surface,
    7845             :                                                                                   &SurfaceData::Area,
    7846          10 :                                                                                   state.dataHeatBal->ExtVentedCavity(Item).SurfPtrs) /
    7847             :                                                                   surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
    7848             : 
    7849             :             // now handle rNumericArgs from input object
    7850           5 :             state.dataHeatBal->ExtVentedCavity(Item).Porosity = state.dataIPShortCut->rNumericArgs(1);
    7851           5 :             state.dataHeatBal->ExtVentedCavity(Item).LWEmitt = state.dataIPShortCut->rNumericArgs(2);
    7852           5 :             state.dataHeatBal->ExtVentedCavity(Item).SolAbsorp = state.dataIPShortCut->rNumericArgs(3);
    7853           5 :             state.dataHeatBal->ExtVentedCavity(Item).HdeltaNPL = state.dataIPShortCut->rNumericArgs(4);
    7854           5 :             state.dataHeatBal->ExtVentedCavity(Item).PlenGapThick = state.dataIPShortCut->rNumericArgs(5);
    7855           5 :             if (state.dataHeatBal->ExtVentedCavity(Item).PlenGapThick <= 0.0) {
    7856           0 :                 ShowSevereError(state, format("{}=\"{}\", invalid .", cCurrentModuleObject, state.dataHeatBal->ExtVentedCavity(Item).Name));
    7857           0 :                 ErrorsFound = true;
    7858           0 :                 ShowContinueError(state,
    7859           0 :                                   format("...because field \"{}\" must be greater than Zero=[{:.2T}].",
    7860           0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    7861           0 :                                          state.dataIPShortCut->rNumericArgs(5)));
    7862           0 :                 continue;
    7863             :             }
    7864           5 :             state.dataHeatBal->ExtVentedCavity(Item).AreaRatio = state.dataIPShortCut->rNumericArgs(6);
    7865           5 :             state.dataHeatBal->ExtVentedCavity(Item).Cv = state.dataIPShortCut->rNumericArgs(7);
    7866           5 :             state.dataHeatBal->ExtVentedCavity(Item).Cd = state.dataIPShortCut->rNumericArgs(8);
    7867             : 
    7868             :             // Fill out data we now know
    7869             :             // sum areas of HT surface areas
    7870             :             //            ExtVentedCavity( Item ).ProjArea = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array
    7871             :             // subscript  usage: Replaced by below
    7872           5 :             state.dataHeatBal->ExtVentedCavity(Item).ProjArea = surfaceArea;
    7873           5 :             if (state.dataHeatBal->ExtVentedCavity(Item).ProjArea <= 0.0) {
    7874           0 :                 ShowSevereError(state, format("{}=\"{}\", invalid .", cCurrentModuleObject, state.dataHeatBal->ExtVentedCavity(Item).Name));
    7875           0 :                 ErrorsFound = true;
    7876           0 :                 ShowContinueError(state,
    7877           0 :                                   format("...because gross area of underlying surfaces must be greater than Zero=[{:.2T}].",
    7878           0 :                                          state.dataHeatBal->ExtVentedCavity(Item).ProjArea));
    7879           0 :                 continue;
    7880             :             }
    7881           5 :             state.dataHeatBal->ExtVentedCavity(Item).ActualArea =
    7882           5 :                 state.dataHeatBal->ExtVentedCavity(Item).ProjArea * state.dataHeatBal->ExtVentedCavity(Item).AreaRatio;
    7883             : 
    7884          10 :             SetupOutputVariable(state,
    7885             :                                 "Surface Exterior Cavity Baffle Surface Temperature",
    7886             :                                 Constant::Units::C,
    7887           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Tbaffle,
    7888             :                                 OutputProcessor::TimeStepType::System,
    7889             :                                 OutputProcessor::StoreType::Average,
    7890           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Name);
    7891          10 :             SetupOutputVariable(state,
    7892             :                                 "Surface Exterior Cavity Air Drybulb Temperature",
    7893             :                                 Constant::Units::C,
    7894           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).TAirCav,
    7895             :                                 OutputProcessor::TimeStepType::System,
    7896             :                                 OutputProcessor::StoreType::Average,
    7897           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Name);
    7898          10 :             SetupOutputVariable(state,
    7899             :                                 "Surface Exterior Cavity Total Natural Ventilation Air Change Rate",
    7900             :                                 Constant::Units::ach,
    7901           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).PassiveACH,
    7902             :                                 OutputProcessor::TimeStepType::System,
    7903             :                                 OutputProcessor::StoreType::Average,
    7904           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Name);
    7905          10 :             SetupOutputVariable(state,
    7906             :                                 "Surface Exterior Cavity Total Natural Ventilation Mass Flow Rate",
    7907             :                                 Constant::Units::kg_s,
    7908           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).PassiveMdotVent,
    7909             :                                 OutputProcessor::TimeStepType::System,
    7910             :                                 OutputProcessor::StoreType::Average,
    7911           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Name);
    7912          10 :             SetupOutputVariable(state,
    7913             :                                 "Surface Exterior Cavity Natural Ventilation from Wind Mass Flow Rate",
    7914             :                                 Constant::Units::kg_s,
    7915           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).PassiveMdotWind,
    7916             :                                 OutputProcessor::TimeStepType::System,
    7917             :                                 OutputProcessor::StoreType::Average,
    7918           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Name);
    7919          10 :             SetupOutputVariable(state,
    7920             :                                 "Surface Exterior Cavity Natural Ventilation from Buoyancy Mass Flow Rate",
    7921             :                                 Constant::Units::kg_s,
    7922           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).PassiveMdotTherm,
    7923             :                                 OutputProcessor::TimeStepType::System,
    7924             :                                 OutputProcessor::StoreType::Average,
    7925           5 :                                 state.dataHeatBal->ExtVentedCavity(Item).Name);
    7926             :         }
    7927         796 :     }
    7928             : 
    7929         796 :     void ExposedFoundationPerimeter::getData(EnergyPlusData &state, bool &ErrorsFound)
    7930             :     {
    7931             : 
    7932             :         int IOStatus; // Used in GetObjectItem
    7933             :         int NumAlphas;
    7934             :         int NumNumbers;
    7935             : 
    7936         796 :         Real64 constexpr tolerance = 1e-6;
    7937             : 
    7938         796 :         constexpr std::string_view cCurrentModuleObject = "SurfaceProperty:ExposedFoundationPerimeter";
    7939         796 :         int numObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    7940             : 
    7941         819 :         for (int obj = 1; obj <= numObjects; ++obj) {
    7942          23 :             int alpF = 1;
    7943          23 :             int numF = 1;
    7944          46 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    7945             :                                                                      cCurrentModuleObject,
    7946             :                                                                      obj,
    7947          23 :                                                                      state.dataIPShortCut->cAlphaArgs,
    7948             :                                                                      NumAlphas,
    7949          23 :                                                                      state.dataIPShortCut->rNumericArgs,
    7950             :                                                                      NumNumbers,
    7951             :                                                                      IOStatus,
    7952          23 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    7953          23 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    7954          23 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    7955          23 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    7956          23 :             int Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    7957          23 :             if (Found == 0) {
    7958           0 :                 ShowSevereError(state, format("{}=\"{}\", did not find matching surface", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    7959           0 :                 ErrorsFound = true;
    7960             :             }
    7961          23 :             alpF++;
    7962          23 :             if (state.dataSurface->Surface(Found).Class != SurfaceClass::Floor) {
    7963           0 :                 ShowWarningError(state,
    7964           0 :                                  format("{}: {}, surface is not a floor surface", cCurrentModuleObject, state.dataSurface->Surface(Found).Name));
    7965           0 :                 ShowContinueError(state, format("{} will not be used", cCurrentModuleObject));
    7966           0 :                 continue;
    7967             :             }
    7968             : 
    7969             :             // Choose calculation method
    7970             : 
    7971             :             enum class CalculationMethod
    7972             :             {
    7973             :                 Invalid = -1,
    7974             :                 TotalExposedPerimeter,
    7975             :                 ExposedPerimeterFraction,
    7976             :                 Bysegment,
    7977             :                 Num
    7978             :             };
    7979             : 
    7980          23 :             constexpr std::array<std::string_view, static_cast<int>(CalculationMethod::Num)> CalculationMethodUC = {
    7981             :                 "TOTALEXPOSEDPERIMETER", "EXPOSEDPERIMETERFRACTION", "BYSEGMENT"};
    7982             :             CalculationMethod calculationMethod =
    7983          23 :                 static_cast<CalculationMethod>(getEnumValue(CalculationMethodUC, state.dataIPShortCut->cAlphaArgs(alpF)));
    7984          23 :             if (calculationMethod != CalculationMethod::TotalExposedPerimeter && calculationMethod != CalculationMethod::ExposedPerimeterFraction &&
    7985          19 :                 calculationMethod != CalculationMethod::Bysegment) {
    7986           0 :                 ShowSevereError(state,
    7987           0 :                                 format("{}=\"{}\", {} is not a valid choice for {}",
    7988             :                                        cCurrentModuleObject,
    7989           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    7990             :                                        calculationMethod,
    7991           0 :                                        state.dataIPShortCut->cAlphaFieldNames(alpF)));
    7992           0 :                 ErrorsFound = true;
    7993             :             }
    7994          23 :             alpF++;
    7995             : 
    7996          23 :             Data data;
    7997          23 :             data.useDetailedExposedPerimeter = true;
    7998             : 
    7999          23 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
    8000           1 :                 if (calculationMethod == CalculationMethod::TotalExposedPerimeter) {
    8001           1 :                     data.exposedFraction = state.dataIPShortCut->rNumericArgs(numF) / state.dataSurface->Surface(Found).Perimeter;
    8002           1 :                     if (data.exposedFraction > 1 + tolerance) {
    8003           0 :                         ShowWarningError(state,
    8004           0 :                                          format("{}: {}, {} is greater than the perimeter of {}",
    8005             :                                                 cCurrentModuleObject,
    8006           0 :                                                 state.dataSurface->Surface(Found).Name,
    8007           0 :                                                 state.dataIPShortCut->cNumericFieldNames(numF),
    8008           0 :                                                 state.dataSurface->Surface(Found).Name));
    8009           0 :                         ShowContinueError(state,
    8010           0 :                                           format("{} perimeter = {}, {} exposed perimeter = {}",
    8011           0 :                                                  state.dataSurface->Surface(Found).Name,
    8012           0 :                                                  state.dataSurface->Surface(Found).Perimeter,
    8013             :                                                  cCurrentModuleObject,
    8014           0 :                                                  state.dataIPShortCut->rNumericArgs(numF)));
    8015           0 :                         ShowContinueError(state,
    8016           0 :                                           format("{} will be set equal to {} perimeter",
    8017           0 :                                                  state.dataIPShortCut->cNumericFieldNames(numF),
    8018           0 :                                                  state.dataSurface->Surface(Found).Name));
    8019           0 :                         data.exposedFraction = 1.0;
    8020             :                     }
    8021             : 
    8022           1 :                     data.useDetailedExposedPerimeter = false;
    8023             :                 } else {
    8024           0 :                     ShowWarningError(state,
    8025           0 :                                      format("{}: {}, {} set as calculation method, but a value has been set for {}. This value will be ignored.",
    8026             :                                             cCurrentModuleObject,
    8027           0 :                                             state.dataSurface->Surface(Found).Name,
    8028             :                                             calculationMethod,
    8029           0 :                                             state.dataIPShortCut->cNumericFieldNames(numF)));
    8030             :                 }
    8031             :             } else {
    8032          22 :                 if (calculationMethod == CalculationMethod::TotalExposedPerimeter) {
    8033           0 :                     ShowSevereError(state,
    8034           0 :                                     format("{}: {}, {} set as calculation method, but no value has been set for {}",
    8035             :                                            cCurrentModuleObject,
    8036           0 :                                            state.dataSurface->Surface(Found).Name,
    8037             :                                            calculationMethod,
    8038           0 :                                            state.dataIPShortCut->cNumericFieldNames(numF)));
    8039           0 :                     ErrorsFound = true;
    8040             :                 }
    8041             :             }
    8042          23 :             numF++;
    8043             : 
    8044          23 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
    8045           3 :                 if (calculationMethod == CalculationMethod::ExposedPerimeterFraction) {
    8046           3 :                     data.exposedFraction = state.dataIPShortCut->rNumericArgs(numF);
    8047           3 :                     data.useDetailedExposedPerimeter = false;
    8048             :                 } else {
    8049           0 :                     ShowWarningError(state,
    8050           0 :                                      format("{}: {}, {} set as calculation method, but a value has been set for {}. This value will be ignored.",
    8051             :                                             cCurrentModuleObject,
    8052           0 :                                             state.dataSurface->Surface(Found).Name,
    8053             :                                             calculationMethod,
    8054           0 :                                             state.dataIPShortCut->cNumericFieldNames(numF)));
    8055             :                 }
    8056             :             } else {
    8057          20 :                 if (calculationMethod == CalculationMethod::ExposedPerimeterFraction) {
    8058           0 :                     ShowSevereError(state,
    8059           0 :                                     format("{}: {}, {} set as calculation method, but no value has been set for {}",
    8060             :                                            cCurrentModuleObject,
    8061           0 :                                            state.dataSurface->Surface(Found).Name,
    8062             :                                            calculationMethod,
    8063           0 :                                            state.dataIPShortCut->cNumericFieldNames(numF)));
    8064           0 :                     ErrorsFound = true;
    8065             :                 }
    8066             :             }
    8067          23 :             numF++;
    8068             : 
    8069          23 :             int numRemainingFields = NumAlphas - (alpF - 1) + NumNumbers - (numF - 1);
    8070          23 :             if (numRemainingFields > 0) {
    8071          19 :                 if (calculationMethod == CalculationMethod::Bysegment) {
    8072          19 :                     if (numRemainingFields != (int)state.dataSurface->Surface(Found).Vertex.size()) {
    8073           0 :                         ShowSevereError(state,
    8074           0 :                                         format("{}: {}, must have equal number of segments as the floor has vertices.{}\" and \"{}\"",
    8075             :                                                cCurrentModuleObject,
    8076           0 :                                                state.dataSurface->Surface(Found).Name,
    8077           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
    8078           0 :                                                state.dataIPShortCut->cNumericFieldNames(numF - 1)));
    8079           0 :                         ShowContinueError(state,
    8080           0 :                                           format("{} number of vertices = {}, {} number of segments = {}",
    8081           0 :                                                  state.dataSurface->Surface(Found).Name,
    8082           0 :                                                  state.dataSurface->Surface(Found).Vertex.size(),
    8083             :                                                  cCurrentModuleObject,
    8084             :                                                  numRemainingFields));
    8085           0 :                         ErrorsFound = true;
    8086             :                     }
    8087          95 :                     for (int segNum = 0; segNum < numRemainingFields; segNum++) {
    8088          76 :                         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "YES")) {
    8089          28 :                             data.isExposedPerimeter.push_back(true);
    8090          48 :                         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "NO")) {
    8091          48 :                             data.isExposedPerimeter.push_back(false);
    8092           0 :                         } else if (state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
    8093           0 :                             ShowSevereError(
    8094             :                                 state,
    8095           0 :                                 format("{}: {}, {} set as calculation method, but no value has been set for {}. Must be \"Yes\" or \"No\".",
    8096             :                                        cCurrentModuleObject,
    8097           0 :                                        state.dataSurface->Surface(Found).Name,
    8098             :                                        calculationMethod,
    8099           0 :                                        state.dataIPShortCut->cAlphaFieldNames(alpF)));
    8100           0 :                             ErrorsFound = true;
    8101             :                         } else {
    8102           0 :                             ShowSevereError(state,
    8103           0 :                                             format("{}: {}, {} invalid [{}]. Must be \"Yes\" or \"No\".",
    8104             :                                                    cCurrentModuleObject,
    8105           0 :                                                    state.dataSurface->Surface(Found).Name,
    8106           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(alpF),
    8107           0 :                                                    state.dataIPShortCut->cAlphaArgs(alpF)));
    8108           0 :                             ErrorsFound = true;
    8109             :                         }
    8110          76 :                         alpF++;
    8111             :                     }
    8112             :                 }
    8113             :             } else {
    8114           4 :                 if (calculationMethod == CalculationMethod::Bysegment) {
    8115           0 :                     ShowSevereError(state,
    8116           0 :                                     format("{}: {}, {} set as calculation method, but no values have been set for Surface Segments Exposed",
    8117             :                                            cCurrentModuleObject,
    8118           0 :                                            state.dataSurface->Surface(Found).Name,
    8119             :                                            calculationMethod));
    8120           0 :                     ErrorsFound = true;
    8121             :                 }
    8122             :             }
    8123          23 :             surfaceMap[Found] = data;
    8124          23 :         }
    8125         796 :     }
    8126             : 
    8127         796 :     void GetSurfaceLocalEnvData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    8128             :     {
    8129             :         // SUBROUTINE INFORMATION:
    8130             :         //       AUTHOR         X LUO
    8131             :         //       DATE WRITTEN   July 2017
    8132             :         //       MODIFIED       na
    8133             :         //       RE-ENGINEERED  na
    8134             : 
    8135             :         // PURPOSE OF THIS SUBROUTINE:
    8136             :         // load input data for Outdoor Air Node for exterior surfaces
    8137             : 
    8138             :         // Using/Aliasing
    8139             :         using namespace DataErrorTracking;
    8140             :         using DataLoopNode::ObjectIsParent;
    8141             :         using NodeInputManager::GetOnlySingleNode;
    8142             :         using OutAirNodeManager::CheckOutAirNodeNumber;
    8143             :         using ScheduleManager::GetScheduleIndex;
    8144             : 
    8145             :         // SUBROUTINE PARAMETER DEFINITIONS:
    8146             :         static constexpr std::string_view RoutineName("GetSurfaceLocalEnvData: ");
    8147             : 
    8148             :         // INTERFACE BLOCK SPECIFICATIONS:na
    8149             :         // DERIVED TYPE DEFINITIONS:na
    8150             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8151             :         int NumAlpha;
    8152             :         int NumNumeric;
    8153             :         int IOStat;
    8154             : 
    8155             :         //-----------------------------------------------------------------------
    8156             :         //                SurfaceProperty:LocalEnvironment
    8157             :         //-----------------------------------------------------------------------
    8158         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    8159         796 :         cCurrentModuleObject = "SurfaceProperty:LocalEnvironment";
    8160         796 :         state.dataSurface->TotSurfLocalEnv = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8161             : 
    8162         796 :         if (state.dataSurface->TotSurfLocalEnv > 0) {
    8163             : 
    8164           4 :             state.dataGlobal->AnyLocalEnvironmentsInModel = true;
    8165             : 
    8166           4 :             if (!allocated(state.dataSurface->SurfLocalEnvironment)) {
    8167           4 :                 state.dataSurface->SurfLocalEnvironment.allocate(state.dataSurface->TotSurfLocalEnv);
    8168             :             }
    8169             : 
    8170         126 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfLocalEnv; ++Loop) {
    8171             : 
    8172         122 :                 auto &SurfLocalEnv = state.dataSurface->SurfLocalEnvironment(Loop);
    8173             : 
    8174         244 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8175             :                                                                          cCurrentModuleObject,
    8176             :                                                                          Loop,
    8177         122 :                                                                          state.dataIPShortCut->cAlphaArgs,
    8178             :                                                                          NumAlpha,
    8179         122 :                                                                          state.dataIPShortCut->rNumericArgs,
    8180             :                                                                          NumNumeric,
    8181             :                                                                          IOStat,
    8182         122 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    8183         122 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    8184         122 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    8185         122 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    8186         122 :                 Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    8187             : 
    8188         122 :                 SurfLocalEnv.Name = state.dataIPShortCut->cAlphaArgs(1);
    8189             : 
    8190             :                 // Assign surface number
    8191         122 :                 int SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface);
    8192         122 :                 if (SurfNum == 0) {
    8193           0 :                     ShowSevereError(state,
    8194           0 :                                     format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8195             :                                            RoutineName,
    8196             :                                            cCurrentModuleObject,
    8197           0 :                                            SurfLocalEnv.Name,
    8198           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2)));
    8199           0 :                     ShowContinueError(state,
    8200           0 :                                       format("{} entered value = \"{}\", no corresponding surface (ref BuildingSurface:Detailed) has been "
    8201             :                                              "found in the input file.",
    8202           0 :                                              state.dataIPShortCut->cAlphaFieldNames(2),
    8203           0 :                                              state.dataIPShortCut->cAlphaArgs(2)));
    8204           0 :                     ErrorsFound = true;
    8205             :                 } else {
    8206         122 :                     SurfLocalEnv.SurfPtr = SurfNum;
    8207             :                 }
    8208             : 
    8209             :                 // Assign Sunlit Fraction Schedule number
    8210         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    8211         102 :                     int SunlitFracSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    8212         102 :                     if (SunlitFracSchedNum == 0) {
    8213           0 :                         ShowSevereError(state,
    8214           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8215             :                                                RoutineName,
    8216             :                                                cCurrentModuleObject,
    8217           0 :                                                SurfLocalEnv.Name,
    8218           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3)));
    8219           0 :                         ShowContinueError(
    8220             :                             state,
    8221           0 :                             format("{} entered value = \"{}\", no corresponding sunlit fraction schedule has been found in the input file.",
    8222           0 :                                    state.dataIPShortCut->cAlphaFieldNames(3),
    8223           0 :                                    state.dataIPShortCut->cAlphaArgs(3)));
    8224           0 :                         ErrorsFound = true;
    8225             :                     } else {
    8226         102 :                         SurfLocalEnv.SunlitFracSchedPtr = SunlitFracSchedNum;
    8227             :                     }
    8228             :                 }
    8229             : 
    8230             :                 // Assign surrounding surfaces object number;
    8231         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
    8232           6 :                     int SurroundingSurfsNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataSurface->SurroundingSurfsProperty);
    8233           6 :                     if (SurroundingSurfsNum == 0) {
    8234           0 :                         ShowSevereError(state,
    8235           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8236             :                                                RoutineName,
    8237             :                                                cCurrentModuleObject,
    8238           0 :                                                SurfLocalEnv.Name,
    8239           0 :                                                state.dataIPShortCut->cAlphaFieldNames(4)));
    8240           0 :                         ShowContinueError(state,
    8241           0 :                                           format("{} entered value = \"{}\", no corresponding surrounding surfaces properties has been found "
    8242             :                                                  "in the input file.",
    8243           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(4),
    8244           0 :                                                  state.dataIPShortCut->cAlphaArgs(4)));
    8245           0 :                         ErrorsFound = true;
    8246             :                     } else {
    8247           6 :                         SurfLocalEnv.SurroundingSurfsPtr = SurroundingSurfsNum;
    8248             :                     }
    8249             :                 }
    8250             : 
    8251             :                 // Assign outdoor air node number;
    8252         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
    8253           2 :                     int NodeNum = GetOnlySingleNode(state,
    8254           2 :                                                     state.dataIPShortCut->cAlphaArgs(5),
    8255             :                                                     ErrorsFound,
    8256             :                                                     DataLoopNode::ConnectionObjectType::SurfacePropertyLocalEnvironment,
    8257           2 :                                                     SurfLocalEnv.Name,
    8258             :                                                     DataLoopNode::NodeFluidType::Air,
    8259             :                                                     DataLoopNode::ConnectionType::Inlet,
    8260             :                                                     NodeInputManager::CompFluidStream::Primary,
    8261             :                                                     ObjectIsParent);
    8262           2 :                     if (NodeNum == 0 && CheckOutAirNodeNumber(state, NodeNum)) {
    8263           0 :                         ShowSevereError(state,
    8264           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8265             :                                                RoutineName,
    8266             :                                                cCurrentModuleObject,
    8267           0 :                                                SurfLocalEnv.Name,
    8268           0 :                                                state.dataIPShortCut->cAlphaFieldNames(5)));
    8269           0 :                         ShowContinueError(state,
    8270           0 :                                           format("{} entered value = \"{}\", no corresponding outdoor air node has been found in the input file.",
    8271           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(5),
    8272           0 :                                                  state.dataIPShortCut->cAlphaArgs(5)));
    8273           0 :                         ErrorsFound = true;
    8274             :                     } else {
    8275           2 :                         SurfLocalEnv.OutdoorAirNodePtr = NodeNum;
    8276             :                     }
    8277             :                 }
    8278             : 
    8279             :                 // get ground surfaces object number;
    8280         122 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) {
    8281          13 :                     int GndSurfsNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(6), state.dataSurface->GroundSurfsProperty);
    8282          13 :                     if (GndSurfsNum == 0) {
    8283           0 :                         ShowSevereError(state,
    8284           0 :                                         format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
    8285             :                                                RoutineName,
    8286             :                                                cCurrentModuleObject,
    8287           0 :                                                SurfLocalEnv.Name,
    8288           0 :                                                state.dataIPShortCut->cAlphaFieldNames(6)));
    8289           0 :                         ShowContinueError(
    8290             :                             state,
    8291           0 :                             format("{} entered value = \"{}\", no corresponding ground surfaces object has been found in the input file.",
    8292           0 :                                    state.dataIPShortCut->cAlphaFieldNames(6),
    8293           0 :                                    state.dataIPShortCut->cAlphaArgs(6)));
    8294           0 :                         ErrorsFound = true;
    8295             :                     } else {
    8296          13 :                         SurfLocalEnv.GroundSurfsPtr = GndSurfsNum;
    8297             :                     }
    8298             :                 }
    8299             :             }
    8300             :         }
    8301             :         // Link surface properties to surface object
    8302       46840 :         for (int SurfLoop = 1; SurfLoop <= state.dataSurface->TotSurfaces; ++SurfLoop) {
    8303       59550 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfLocalEnv; ++Loop) {
    8304       13506 :                 auto &SurfLocalEnv = state.dataSurface->SurfLocalEnvironment(Loop);
    8305       13506 :                 if (SurfLocalEnv.SurfPtr == SurfLoop) {
    8306         122 :                     auto &surface = state.dataSurface->Surface(SurfLoop);
    8307         122 :                     if (SurfLocalEnv.OutdoorAirNodePtr != 0) {
    8308           2 :                         surface.SurfLinkedOutAirNode = SurfLocalEnv.OutdoorAirNodePtr;
    8309             :                     }
    8310         122 :                     if (SurfLocalEnv.SunlitFracSchedPtr != 0) {
    8311         102 :                         surface.SurfSchedExternalShadingFrac = true;
    8312         102 :                         surface.SurfExternalShadingSchInd = SurfLocalEnv.SunlitFracSchedPtr;
    8313             :                     }
    8314         122 :                     if (SurfLocalEnv.SurroundingSurfsPtr != 0) {
    8315           6 :                         surface.SurfHasSurroundingSurfProperty = true;
    8316           6 :                         surface.SurfSurroundingSurfacesNum = SurfLocalEnv.SurroundingSurfsPtr;
    8317           6 :                         surface.ViewFactorSrdSurfs =
    8318           6 :                             state.dataSurface->SurroundingSurfsProperty(surface.SurfSurroundingSurfacesNum).SurfsViewFactorSum;
    8319           6 :                         if (surface.ViewFactorSrdSurfs == 0.0) {
    8320           0 :                             surface.SurfHasSurroundingSurfProperty = false;
    8321             :                         }
    8322             :                     }
    8323         122 :                     if (SurfLocalEnv.GroundSurfsPtr != 0) {
    8324          13 :                         surface.IsSurfPropertyGndSurfacesDefined = true;
    8325          13 :                         surface.UseSurfPropertyGndSurfTemp = true;
    8326          13 :                         surface.UseSurfPropertyGndSurfRefl = true;
    8327          13 :                         surface.SurfPropertyGndSurfIndex = SurfLocalEnv.GroundSurfsPtr;
    8328             :                     }
    8329             :                 }
    8330             :             }
    8331             :         }
    8332         796 :     }
    8333             : 
    8334         796 :     void GetSurfaceSrdSurfsData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    8335             :     {
    8336             :         // SUBROUTINE INFORMATION:
    8337             :         //       AUTHOR         X LUO
    8338             :         //       DATE WRITTEN   July 2017
    8339             :         //       MODIFIED       na
    8340             :         //       RE-ENGINEERED  na
    8341             : 
    8342             :         // PURPOSE OF THIS SUBROUTINE:
    8343             :         // load input data for surrounding surfaces properties for exterior surfaces
    8344             : 
    8345             :         // Using/Aliasing
    8346             :         using namespace DataErrorTracking;
    8347             :         using DataLoopNode::ObjectIsParent;
    8348             :         using NodeInputManager::GetOnlySingleNode;
    8349             :         using OutAirNodeManager::CheckOutAirNodeNumber;
    8350             :         using ScheduleManager::GetScheduleIndex;
    8351             : 
    8352             :         // INTERFACE BLOCK SPECIFICATIONS:na
    8353             :         // DERIVED TYPE DEFINITIONS:na
    8354             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8355             :         int NumAlpha;
    8356             :         int NumNumeric;
    8357             :         int IOStat;
    8358             :         int TotSrdSurfProperties;
    8359             : 
    8360             :         //-----------------------------------------------------------------------
    8361             :         //                SurfaceProperty:SurroundingSurfaces
    8362             :         //-----------------------------------------------------------------------
    8363         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    8364         796 :         cCurrentModuleObject = "SurfaceProperty:SurroundingSurfaces";
    8365         796 :         TotSrdSurfProperties = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8366             : 
    8367         796 :         if (TotSrdSurfProperties > 0) {
    8368             : 
    8369           2 :             if (!allocated(state.dataSurface->SurroundingSurfsProperty)) {
    8370           2 :                 state.dataSurface->SurroundingSurfsProperty.allocate(TotSrdSurfProperties);
    8371             :             }
    8372             : 
    8373           8 :             for (int Loop = 1; Loop <= TotSrdSurfProperties; ++Loop) {
    8374             : 
    8375           6 :                 auto &SrdSurfsProp = state.dataSurface->SurroundingSurfsProperty(Loop);
    8376             : 
    8377          12 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8378             :                                                                          cCurrentModuleObject,
    8379             :                                                                          Loop,
    8380           6 :                                                                          state.dataIPShortCut->cAlphaArgs,
    8381             :                                                                          NumAlpha,
    8382           6 :                                                                          state.dataIPShortCut->rNumericArgs,
    8383             :                                                                          NumNumeric,
    8384             :                                                                          IOStat,
    8385           6 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    8386           6 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    8387           6 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    8388           6 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    8389           6 :                 Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    8390             : 
    8391             :                 // A1: Name
    8392           6 :                 SrdSurfsProp.Name = state.dataIPShortCut->cAlphaArgs(1);
    8393             : 
    8394             :                 // N1: sky view factor
    8395           6 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(1)) {
    8396           6 :                     SrdSurfsProp.SkyViewFactor = state.dataIPShortCut->rNumericArgs(1);
    8397           6 :                     SrdSurfsProp.IsSkyViewFactorSet = true;
    8398             :                 }
    8399             : 
    8400             :                 // A2: sky temp sch name
    8401           6 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    8402           0 :                     SrdSurfsProp.SkyTempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    8403             :                 }
    8404             : 
    8405             :                 // N2: ground view factor
    8406           6 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
    8407           3 :                     SrdSurfsProp.GroundViewFactor = state.dataIPShortCut->rNumericArgs(2);
    8408           3 :                     SrdSurfsProp.IsGroundViewFactorSet = true;
    8409             :                 }
    8410             : 
    8411             :                 // A3: ground temp sch name
    8412           6 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    8413           0 :                     SrdSurfsProp.GroundTempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    8414             :                 }
    8415             : 
    8416             :                 // The object requires at least one srd surface input, each surface requires a set of 3 fields (2 Alpha fields Name and Temp
    8417             :                 // Sch Name and 1 Num fields View Factor)
    8418           6 :                 if (NumAlpha < 5) {
    8419           0 :                     ShowSevereError(state, format("{} = \"{}\" is not defined correctly.", cCurrentModuleObject, SrdSurfsProp.Name));
    8420           0 :                     ShowContinueError(state, "At lease one set of surrounding surface properties should be defined.");
    8421           0 :                     ErrorsFound = true;
    8422           0 :                     continue;
    8423             :                 }
    8424           6 :                 if ((NumAlpha - 3) / 2 != (NumNumeric - 2)) {
    8425           0 :                     ShowSevereError(state, format("{} = \"{}\" is not defined correctly.", cCurrentModuleObject, SrdSurfsProp.Name));
    8426           0 :                     ShowContinueError(state, "Check number of input fields for each surrounding surface.");
    8427           0 :                     ErrorsFound = true;
    8428           0 :                     continue;
    8429             :                 }
    8430             :                 // Read surrounding surfaces properties
    8431           6 :                 SrdSurfsProp.TotSurroundingSurface = NumNumeric - 2;
    8432           6 :                 SrdSurfsProp.SurroundingSurfs.allocate(SrdSurfsProp.TotSurroundingSurface);
    8433          14 :                 for (int SurfLoop = 1; SurfLoop <= SrdSurfsProp.TotSurroundingSurface; ++SurfLoop) {
    8434           8 :                     SrdSurfsProp.SurroundingSurfs(SurfLoop).Name = state.dataIPShortCut->cAlphaArgs(SurfLoop * 2 + 2);
    8435           8 :                     SrdSurfsProp.SurroundingSurfs(SurfLoop).ViewFactor = state.dataIPShortCut->rNumericArgs(SurfLoop + 2);
    8436           8 :                     SrdSurfsProp.SurroundingSurfs(SurfLoop).TempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(SurfLoop * 2 + 3));
    8437           8 :                     SrdSurfsProp.SurfsViewFactorSum += SrdSurfsProp.SurroundingSurfs(SurfLoop).ViewFactor;
    8438             :                 }
    8439             :             }
    8440             :         }
    8441         796 :     }
    8442             : 
    8443         796 :     void GetSurfaceGroundSurfsData(EnergyPlusData &state, bool &ErrorsFound)
    8444             :     {
    8445             : 
    8446         796 :         std::string const cCurrentModuleObject = "SurfaceProperty:GroundSurfaces";
    8447         796 :         state.dataSurface->TotSurfPropGndSurfs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8448         796 :         auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
    8449         796 :         if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
    8450         795 :             if (state.dataSurface->TotSurfPropGndSurfs > 0) ErrorsFound = true;
    8451         795 :             return;
    8452             :         } else {
    8453           1 :             auto &instancesValue = instances.value();
    8454           6 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    8455           5 :                 auto const &fields = instance.value();
    8456           5 :                 std::string const &thisObjectName = instance.key();
    8457           5 :                 GroundSurfacesProperty thisGndSurfsObj;
    8458           5 :                 thisGndSurfsObj.Name = Util::makeUPPER(thisObjectName);
    8459           5 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
    8460           5 :                 auto groundSurfaces = fields.find("ground_surfaces");
    8461           5 :                 if (groundSurfaces != fields.end()) {
    8462           5 :                     auto &groundSurfacesArray = groundSurfaces.value();
    8463           5 :                     thisGndSurfsObj.NumGndSurfs = groundSurfacesArray.size();
    8464          16 :                     for (auto &groundSurface : groundSurfacesArray) {
    8465          11 :                         GroundSurfacesData thisGndSurf;
    8466          11 :                         auto GndSurfName = groundSurface.find("ground_surface_name");
    8467          11 :                         if (GndSurfName != groundSurface.end()) {
    8468          11 :                             std::string ground_surf_name = GndSurfName.value().get<std::string>();
    8469          11 :                             if (!ground_surf_name.empty()) {
    8470          11 :                                 thisGndSurf.Name = Util::makeUPPER(ground_surf_name);
    8471             :                             }
    8472          11 :                         }
    8473          11 :                         auto groundSurfViewFactor = groundSurface.find("ground_surface_view_factor");
    8474          11 :                         if (groundSurfViewFactor != groundSurface.end()) {
    8475          11 :                             thisGndSurf.ViewFactor = groundSurfViewFactor.value().get<Real64>();
    8476          11 :                             thisGndSurfsObj.IsGroundViewFactorSet = true;
    8477             :                         }
    8478          11 :                         auto TempSchName = groundSurface.find("ground_surface_temperature_schedule_name");
    8479          11 :                         if (TempSchName != groundSurface.end()) {
    8480          10 :                             std::string gnd_surf_TempSchName = TempSchName.value().get<std::string>();
    8481          10 :                             if (!gnd_surf_TempSchName.empty()) {
    8482          10 :                                 thisGndSurf.TempSchPtr = ScheduleManager::GetScheduleIndex(state, Util::makeUPPER(gnd_surf_TempSchName));
    8483             :                             }
    8484          10 :                         }
    8485          11 :                         auto ReflSchName = groundSurface.find("ground_surface_reflectance_schedule_name");
    8486          11 :                         if (ReflSchName != groundSurface.end()) {
    8487          10 :                             std::string gnd_surf_ReflSchName = ReflSchName.value().get<std::string>();
    8488          10 :                             if (!gnd_surf_ReflSchName.empty()) {
    8489          10 :                                 thisGndSurf.ReflSchPtr = ScheduleManager::GetScheduleIndex(state, Util::makeUPPER(gnd_surf_ReflSchName));
    8490             :                             }
    8491          10 :                         }
    8492          11 :                         thisGndSurfsObj.GndSurfs.push_back(thisGndSurf);
    8493          16 :                     }
    8494             :                 }
    8495          16 :                 for (int gSurfNum = 1; gSurfNum <= thisGndSurfsObj.NumGndSurfs; gSurfNum++) {
    8496          11 :                     thisGndSurfsObj.SurfsViewFactorSum += thisGndSurfsObj.GndSurfs(gSurfNum).ViewFactor;
    8497             :                 }
    8498           5 :                 state.dataSurface->GroundSurfsProperty.push_back(thisGndSurfsObj);
    8499           6 :             }
    8500             :         }
    8501             :         // set report variables
    8502           1 :         if (state.dataSurface->TotSurfPropGndSurfs > 0) {
    8503           6 :             for (int Loop = 1; Loop <= state.dataSurface->TotSurfPropGndSurfs; Loop++) {
    8504           5 :                 bool SetTempSchReportVar = true;
    8505           5 :                 bool SetReflSchReportVar = true;
    8506           5 :                 auto &thisGndSurfsObj = state.dataSurface->GroundSurfsProperty(Loop);
    8507          16 :                 for (int gSurfNum = 1; gSurfNum <= thisGndSurfsObj.NumGndSurfs; gSurfNum++) {
    8508          11 :                     if (thisGndSurfsObj.GndSurfs(gSurfNum).TempSchPtr != 0 && SetTempSchReportVar) {
    8509           8 :                         SetupOutputVariable(state,
    8510             :                                             "Surfaces Property Ground Surfaces Average Temperature",
    8511             :                                             Constant::Units::C,
    8512           4 :                                             thisGndSurfsObj.SurfsTempAvg,
    8513             :                                             OutputProcessor::TimeStepType::Zone,
    8514             :                                             OutputProcessor::StoreType::Average,
    8515           4 :                                             thisGndSurfsObj.Name);
    8516           4 :                         SetTempSchReportVar = false;
    8517             :                     }
    8518          11 :                     if (thisGndSurfsObj.GndSurfs(gSurfNum).ReflSchPtr != 0 && SetReflSchReportVar) {
    8519           8 :                         SetupOutputVariable(state,
    8520             :                                             "Surfaces Property Ground Surfaces Average Reflectance",
    8521             :                                             Constant::Units::None,
    8522           4 :                                             thisGndSurfsObj.SurfsReflAvg,
    8523             :                                             OutputProcessor::TimeStepType::Zone,
    8524             :                                             OutputProcessor::StoreType::Average,
    8525           4 :                                             thisGndSurfsObj.Name);
    8526           4 :                         SetReflSchReportVar = false;
    8527             :                     }
    8528             :                 }
    8529             :             }
    8530             :         }
    8531        1591 :     }
    8532             : 
    8533         796 :     void GetSurfaceHeatTransferAlgorithmOverrides(EnergyPlusData &state, bool &ErrorsFound)
    8534             :     {
    8535             : 
    8536             :         // SUBROUTINE INFORMATION:
    8537             :         //       AUTHOR         B. Griffith, portions from ApplyConvectionValue by Linda Lawrie
    8538             :         //       DATE WRITTEN   July 2012
    8539             :         //       MODIFIED       na
    8540             :         //       RE-ENGINEERED  na
    8541             : 
    8542             :         // PURPOSE OF THIS SUBROUTINE:
    8543             :         // <description>
    8544             : 
    8545             :         // Using/Aliasing
    8546             : 
    8547             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8548             :         int CountHTAlgoObjectsSingleSurf;
    8549             :         int CountHTAlgoObjectsMultiSurf;
    8550             :         int CountHTAlgoObjectsSurfList;
    8551             :         int IOStatus; // Used in GetObjectItem
    8552         796 :         bool ErrorsFoundSingleSurf(false);
    8553         796 :         bool ErrorsFoundMultiSurf(false);
    8554         796 :         bool ErrorsFoundSurfList(false);
    8555         796 :         bool ErrorsFoundByConstruct(false);
    8556             :         DataSurfaces::HeatTransferModel tmpAlgoInput;
    8557             :         int Item;
    8558             :         int Item1;
    8559             :         int NumAlphas;
    8560             :         int NumNumbers;
    8561             :         int Found;
    8562             :         bool SurfacesOfType;
    8563             :         int SurfNum;
    8564             :         //  INTEGER :: Index
    8565             :         int NumEMPDMat;
    8566             :         int NumPCMat;
    8567             :         int NumVTCMat;
    8568             :         int NumHAMTMat1;
    8569             :         int NumHAMTMat2;
    8570             :         int NumHAMTMat3;
    8571             :         int NumHAMTMat4;
    8572             :         int NumHAMTMat5;
    8573             :         int NumHAMTMat6;
    8574             :         int SumHAMTMat;
    8575             :         bool msgneeded;
    8576             : 
    8577         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    8578         796 :         cCurrentModuleObject = "SurfaceProperty:HeatBalanceSourceTerm";
    8579         796 :         int CountAddHeatSourceSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8580             : 
    8581         800 :         for (Item = 1; Item <= CountAddHeatSourceSurf; ++Item) {
    8582           8 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8583             :                                                                      cCurrentModuleObject,
    8584             :                                                                      Item,
    8585           4 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8586             :                                                                      NumAlphas,
    8587           4 :                                                                      state.dataIPShortCut->rNumericArgs,
    8588             :                                                                      NumNumbers,
    8589             :                                                                      IOStatus,
    8590           4 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8591           4 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8592           4 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8593           4 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8594           4 :             Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    8595             : 
    8596           4 :             if (Found == 0) {
    8597           0 :                 ShowSevereError(state,
    8598           0 :                                 format("{}=\"{}\", did not find matching surface.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    8599           0 :                 ErrorsFound = true;
    8600           8 :             } else if (state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule ||
    8601           4 :                        state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule) {
    8602           0 :                 ShowSevereError(state,
    8603           0 :                                 format("{}=\"{}\", multiple SurfaceProperty:HeatBalanceSourceTerm objects applied to the same surface.",
    8604             :                                        cCurrentModuleObject,
    8605           0 :                                        state.dataIPShortCut->cAlphaArgs(1)));
    8606           0 :                 ErrorsFound = true;
    8607             :             }
    8608             : 
    8609           4 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    8610           1 :                 state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule =
    8611           1 :                     ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
    8612           1 :                 if (state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule == 0) {
    8613           0 :                     ShowSevereError(state,
    8614           0 :                                     format("{}=\"{}\", cannot find the matching Schedule: {}=\"{}",
    8615             :                                            cCurrentModuleObject,
    8616           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8617           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    8618           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    8619           0 :                     ErrorsFound = true;
    8620             :                 } else {
    8621           1 :                     state.dataSurface->allInsideSourceSurfaceList.emplace_back(Found);
    8622             :                 }
    8623             :             }
    8624             : 
    8625           4 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    8626           3 :                 state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule =
    8627           3 :                     ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    8628           3 :                 if (state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule == 0) {
    8629           0 :                     ShowSevereError(state,
    8630           0 :                                     format("{}=\"{}\", cannot find the matching Schedule: {}=\"{}",
    8631             :                                            cCurrentModuleObject,
    8632           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8633           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    8634           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    8635           0 :                     ErrorsFound = true;
    8636           3 :                 } else if (state.dataSurface->Surface(Found).OSCPtr > 0) {
    8637           0 :                     ShowSevereError(state,
    8638           0 :                                     format("{}=\"SurfaceProperty:HeatBalanceSourceTerm\", cannot be specified for OtherSideCoefficient Surface={}",
    8639             :                                            cCurrentModuleObject,
    8640           0 :                                            state.dataIPShortCut->cAlphaArgs(1)));
    8641           0 :                     ErrorsFound = true;
    8642             :                 } else {
    8643           3 :                     state.dataSurface->allOutsideSourceSurfaceList.emplace_back(Found);
    8644             :                 }
    8645             :             }
    8646             : 
    8647           5 :             if (state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule == 0 &&
    8648           1 :                 state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule == 0) {
    8649           0 :                 ShowSevereError(
    8650             :                     state,
    8651           0 :                     format("{}=\"{}\", no schedule defined for additional heat source.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    8652           0 :                 ErrorsFound = true;
    8653             :             }
    8654             :         }
    8655             : 
    8656             :         // first initialize each heat transfer surface with the overall model type, array assignment
    8657       46840 :         for (auto &e : state.dataSurface->Surface)
    8658       46840 :             e.HeatTransferAlgorithm = state.dataHeatBal->OverallHeatTransferSolutionAlgo;
    8659             : 
    8660         796 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm";
    8661         796 :         CountHTAlgoObjectsSingleSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8662             : 
    8663         796 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm";
    8664         798 :         for (Item = 1; Item <= CountHTAlgoObjectsSingleSurf; ++Item) {
    8665           4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8666             :                                                                      cCurrentModuleObject,
    8667             :                                                                      Item,
    8668           2 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8669             :                                                                      NumAlphas,
    8670           2 :                                                                      state.dataIPShortCut->rNumericArgs,
    8671             :                                                                      NumNumbers,
    8672             :                                                                      IOStatus,
    8673           2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8674           2 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8675           2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8676           2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8677           2 :             ErrorsFoundSingleSurf = false;
    8678           2 :             Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    8679             : 
    8680           2 :             if (Found == 0) {
    8681           0 :                 ShowSevereError(state,
    8682           0 :                                 format("{}=\"{}\", did not find matching surface.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    8683           0 :                 ErrorsFoundSingleSurf = true;
    8684             :             }
    8685             : 
    8686             :             {
    8687           2 :                 std::string const &SELECT_CASE_var = state.dataIPShortCut->cAlphaArgs(2);
    8688             : 
    8689           2 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8690           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8691           0 :                     state.dataHeatBal->AnyCTF = true;
    8692           2 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8693           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8694           1 :                     state.dataHeatBal->AnyEMPD = true;
    8695           1 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8696           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8697           0 :                     state.dataHeatBal->AnyHAMT = true;
    8698           1 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8699           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8700           1 :                     state.dataHeatBal->AnyCondFD = true;
    8701             :                 } else {
    8702           0 :                     ShowSevereError(state,
    8703           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    8704             :                                            cCurrentModuleObject,
    8705           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8706           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    8707           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    8708           0 :                     ErrorsFoundSingleSurf = true;
    8709             :                 }
    8710             :             }
    8711             : 
    8712           2 :             if (!ErrorsFoundSingleSurf) {
    8713           2 :                 state.dataSurface->Surface(Found).HeatTransferAlgorithm = tmpAlgoInput;
    8714             :             } else {
    8715           0 :                 ErrorsFound = true;
    8716             :             }
    8717             :         } // single surface heat transfer algorithm override
    8718             : 
    8719         796 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:MultipleSurface";
    8720         796 :         CountHTAlgoObjectsMultiSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8721             : 
    8722         796 :         for (Item = 1; Item <= CountHTAlgoObjectsMultiSurf; ++Item) {
    8723           0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8724             :                                                                      cCurrentModuleObject,
    8725             :                                                                      Item,
    8726           0 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8727             :                                                                      NumAlphas,
    8728           0 :                                                                      state.dataIPShortCut->rNumericArgs,
    8729             :                                                                      NumNumbers,
    8730             :                                                                      IOStatus,
    8731           0 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8732           0 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8733           0 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8734           0 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8735           0 :             ErrorsFoundMultiSurf = false;
    8736             :             {
    8737           0 :                 std::string const &SELECT_CASE_var = state.dataIPShortCut->cAlphaArgs(3);
    8738             : 
    8739           0 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8740           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8741           0 :                     state.dataHeatBal->AnyCTF = true;
    8742           0 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8743           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8744           0 :                     state.dataHeatBal->AnyEMPD = true;
    8745           0 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8746           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8747           0 :                     state.dataHeatBal->AnyHAMT = true;
    8748           0 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8749           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8750           0 :                     state.dataHeatBal->AnyCondFD = true;
    8751             :                 } else {
    8752           0 :                     ShowSevereError(state,
    8753           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    8754             :                                            cCurrentModuleObject,
    8755           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8756           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    8757           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    8758           0 :                     ErrorsFoundMultiSurf = true;
    8759             :                 }
    8760             :             }
    8761             : 
    8762             :             {
    8763           0 :                 std::string const &SELECT_CASE_var = state.dataIPShortCut->cAlphaArgs(2);
    8764             : 
    8765           0 :                 if (SELECT_CASE_var == "ALLEXTERIORSURFACES") {
    8766           0 :                     SurfacesOfType = false;
    8767           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8768           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8769           0 :                         if (!surf.HeatTransSurf) continue;
    8770           0 :                         if (surf.ExtBoundCond > 0) continue; // Interior surfaces
    8771           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8772           0 :                         SurfacesOfType = true;
    8773           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8774             :                     }
    8775             : 
    8776           0 :                 } else if (SELECT_CASE_var == "ALLEXTERIORWALLS") {
    8777           0 :                     SurfacesOfType = false;
    8778           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8779           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8780           0 :                         if (!surf.HeatTransSurf) continue;
    8781           0 :                         if (surf.ExtBoundCond > 0) continue; // Interior surfaces
    8782             : 
    8783           0 :                         if (surf.Class != SurfaceClass::Wall) continue;
    8784           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8785           0 :                         SurfacesOfType = true;
    8786           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8787             :                     }
    8788             : 
    8789           0 :                 } else if (SELECT_CASE_var == "ALLEXTERIORROOFS") {
    8790           0 :                     SurfacesOfType = false;
    8791           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8792           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8793           0 :                         if (!surf.HeatTransSurf) continue;
    8794           0 :                         if (surf.ExtBoundCond > 0) continue; // Interior surfaces
    8795           0 :                         if (surf.Class != SurfaceClass::Roof) continue;
    8796           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8797           0 :                         SurfacesOfType = true;
    8798           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8799             :                     }
    8800             : 
    8801           0 :                 } else if (SELECT_CASE_var == "ALLEXTERIORFLOORS") {
    8802           0 :                     SurfacesOfType = false;
    8803           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8804           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8805           0 :                         if (!surf.HeatTransSurf) continue;
    8806           0 :                         if (surf.ExtBoundCond > 0) continue; // Interior surfaces
    8807           0 :                         if (surf.Class != SurfaceClass::Floor) continue;
    8808           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8809           0 :                         SurfacesOfType = true;
    8810           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8811             :                     }
    8812             : 
    8813           0 :                 } else if (SELECT_CASE_var == "ALLGROUNDCONTACTSURFACES") {
    8814           0 :                     SurfacesOfType = false;
    8815           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8816           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8817           0 :                         if (!surf.HeatTransSurf) continue;
    8818           0 :                         if (surf.ExtBoundCond != Ground) continue; // ground BC
    8819           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8820           0 :                         SurfacesOfType = true;
    8821           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8822             :                     }
    8823           0 :                 } else if (SELECT_CASE_var == "ALLINTERIORSURFACES") {
    8824           0 :                     SurfacesOfType = false;
    8825           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8826           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8827           0 :                         if (!surf.HeatTransSurf) continue;
    8828           0 :                         if (surf.ExtBoundCond <= 0) continue; // Exterior surfaces
    8829           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8830           0 :                         SurfacesOfType = true;
    8831           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8832             :                     }
    8833             : 
    8834           0 :                 } else if (SELECT_CASE_var == "ALLINTERIORWALLS") {
    8835           0 :                     SurfacesOfType = false;
    8836           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8837           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8838           0 :                         if (!surf.HeatTransSurf) continue;
    8839           0 :                         if (surf.ExtBoundCond <= 0) continue; // Exterior surfaces
    8840           0 :                         if (surf.Class != SurfaceClass::Wall) continue;
    8841           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8842           0 :                         SurfacesOfType = true;
    8843           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8844             :                     }
    8845             : 
    8846           0 :                 } else if ((SELECT_CASE_var == "ALLINTERIORROOFS") || (SELECT_CASE_var == "ALLINTERIORCEILINGS")) {
    8847           0 :                     SurfacesOfType = false;
    8848           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8849           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8850           0 :                         if (!surf.HeatTransSurf) continue;
    8851           0 :                         if (surf.ExtBoundCond <= 0) continue; // Exterior surfaces
    8852           0 :                         if (surf.Class != SurfaceClass::Roof) continue;
    8853           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8854           0 :                         SurfacesOfType = true;
    8855           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8856             :                     }
    8857             : 
    8858           0 :                 } else if (SELECT_CASE_var == "ALLINTERIORFLOORS") {
    8859           0 :                     SurfacesOfType = false;
    8860           0 :                     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    8861           0 :                         auto &surf = state.dataSurface->Surface(SurfNum);
    8862           0 :                         if (!surf.HeatTransSurf) continue;
    8863           0 :                         if (surf.ExtBoundCond <= 0) continue; // Exterior surfaces
    8864           0 :                         if (surf.Class != SurfaceClass::Floor) continue;
    8865           0 :                         if (state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
    8866           0 :                         SurfacesOfType = true;
    8867           0 :                         surf.HeatTransferAlgorithm = tmpAlgoInput;
    8868             :                     }
    8869             :                 } else {
    8870           0 :                     SurfacesOfType = false;
    8871           0 :                     ShowSevereError(state,
    8872           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    8873             :                                            cCurrentModuleObject,
    8874           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8875           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    8876           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    8877           0 :                     ErrorsFoundMultiSurf = true;
    8878             :                 }
    8879             :             }
    8880             : 
    8881           0 :             if (!SurfacesOfType) {
    8882           0 :                 ShowWarningError(
    8883             :                     state,
    8884           0 :                     format("In {}=\"{}\", for Multiple Surface Assignment=\"{}\", there were no surfaces of that type found for assignment.",
    8885             :                            cCurrentModuleObject,
    8886           0 :                            state.dataIPShortCut->cAlphaArgs(1),
    8887           0 :                            state.dataIPShortCut->cAlphaArgs(2)));
    8888             :             }
    8889           0 :             if (ErrorsFoundMultiSurf) ErrorsFound = true;
    8890             : 
    8891             :         } // multi surface heat transfer algo override
    8892             : 
    8893         796 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:SurfaceList";
    8894         796 :         CountHTAlgoObjectsSurfList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8895         797 :         for (Item = 1; Item <= CountHTAlgoObjectsSurfList; ++Item) {
    8896           2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8897             :                                                                      cCurrentModuleObject,
    8898             :                                                                      Item,
    8899           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8900             :                                                                      NumAlphas,
    8901           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    8902             :                                                                      NumNumbers,
    8903             :                                                                      IOStatus,
    8904           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8905           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8906           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8907           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8908           1 :             ErrorsFoundSurfList = false;
    8909             :             {
    8910           1 :                 std::string const &SELECT_CASE_var = state.dataIPShortCut->cAlphaArgs(2);
    8911             : 
    8912           1 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8913           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8914           0 :                     state.dataHeatBal->AnyCTF = true;
    8915           1 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8916           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8917           1 :                     state.dataHeatBal->AnyEMPD = true;
    8918           0 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8919           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8920           0 :                     state.dataHeatBal->AnyHAMT = true;
    8921           0 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8922           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8923           0 :                     state.dataHeatBal->AnyCondFD = true;
    8924             :                 } else {
    8925           0 :                     ShowSevereError(state,
    8926           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    8927             :                                            cCurrentModuleObject,
    8928           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8929           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    8930           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    8931           0 :                     ErrorsFoundSurfList = true;
    8932             :                 }
    8933             :             }
    8934             : 
    8935           3 :             for (Item1 = 3; Item1 <= NumAlphas; ++Item1) {
    8936             : 
    8937           2 :                 Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(Item1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
    8938             : 
    8939           2 :                 if (Found == 0) {
    8940           0 :                     ShowSevereError(state,
    8941           0 :                                     format("{}=\"{}\", did not find matching surface.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    8942           0 :                     ShowContinueError(state, format("Name of surface not found = \"{}\"", state.dataIPShortCut->cAlphaArgs(Item1)));
    8943           0 :                     ErrorsFoundSurfList = true;
    8944             :                 }
    8945             : 
    8946           2 :                 if (!ErrorsFoundSurfList) {
    8947           2 :                     state.dataSurface->Surface(Found).HeatTransferAlgorithm = tmpAlgoInput;
    8948             :                 } else {
    8949           0 :                     ErrorsFound = true;
    8950             :                 }
    8951             :             }
    8952             :         }
    8953             : 
    8954         796 :         cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:Construction";
    8955         796 :         CountHTAlgoObjectsSurfList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    8956         797 :         for (Item = 1; Item <= CountHTAlgoObjectsSurfList; ++Item) {
    8957           2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    8958             :                                                                      cCurrentModuleObject,
    8959             :                                                                      Item,
    8960           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    8961             :                                                                      NumAlphas,
    8962           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    8963             :                                                                      NumNumbers,
    8964             :                                                                      IOStatus,
    8965           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    8966           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    8967           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    8968           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    8969           1 :             ErrorsFoundByConstruct = false;
    8970             :             {
    8971           1 :                 std::string const &SELECT_CASE_var = state.dataIPShortCut->cAlphaArgs(2);
    8972             : 
    8973           1 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
    8974           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
    8975           0 :                     state.dataHeatBal->AnyCTF = true;
    8976           1 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
    8977           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
    8978           0 :                     state.dataHeatBal->AnyEMPD = true;
    8979           1 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
    8980           1 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
    8981           1 :                     state.dataHeatBal->AnyHAMT = true;
    8982           0 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
    8983           0 :                     tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
    8984           0 :                     state.dataHeatBal->AnyCondFD = true;
    8985             :                 } else {
    8986           0 :                     ShowSevereError(state,
    8987           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
    8988             :                                            cCurrentModuleObject,
    8989           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    8990           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    8991           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    8992           0 :                     ErrorsFoundByConstruct = true;
    8993             :                 }
    8994             :             }
    8995             : 
    8996           1 :             Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    8997           1 :             if (Found == 0) {
    8998           0 :                 ShowSevereError(state,
    8999           0 :                                 format("{}=\"{}\", invalid {}=\"{}",
    9000             :                                        cCurrentModuleObject,
    9001           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    9002           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    9003           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
    9004           0 :                 ErrorsFoundByConstruct = true;
    9005             :             }
    9006             : 
    9007           1 :             if (!ErrorsFoundByConstruct) {
    9008           7 :                 for (Item1 = 1; Item1 <= state.dataSurface->TotSurfaces; ++Item1) {
    9009           6 :                     if (state.dataSurface->Surface(Item1).Construction == Found) {
    9010           1 :                         state.dataSurface->Surface(Item1).HeatTransferAlgorithm = tmpAlgoInput;
    9011             :                     }
    9012             :                 }
    9013             :             }
    9014             :         }
    9015             : 
    9016             :         // Change algorithm for Kiva and air boundary foundation surfaces
    9017       46840 :         for (auto &surf : state.dataSurface->Surface) {
    9018       46044 :             if (surf.ExtBoundCond == KivaFoundation) {
    9019          38 :                 surf.HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::Kiva;
    9020          38 :                 state.dataHeatBal->AnyKiva = true;
    9021             :             }
    9022         796 :         }
    9023             : 
    9024             :         // test for missing materials for algorithms selected
    9025         796 :         NumEMPDMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:MoisturePenetrationDepth:Settings");
    9026         796 :         NumPCMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:PhaseChange") +
    9027         796 :                    state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:PhaseChangeHysteresis");
    9028         796 :         NumVTCMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:VariableThermalConductivity");
    9029         796 :         NumHAMTMat1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Settings");
    9030             :         NumHAMTMat2 =
    9031         796 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm");
    9032         796 :         NumHAMTMat3 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Suction");
    9033         796 :         NumHAMTMat4 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Redistribution");
    9034         796 :         NumHAMTMat5 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Diffusion");
    9035             :         NumHAMTMat6 =
    9036         796 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity");
    9037         796 :         SumHAMTMat = NumHAMTMat1 + NumHAMTMat2 + NumHAMTMat3 + NumHAMTMat4 + NumHAMTMat5 + NumHAMTMat6;
    9038         796 :         msgneeded = false;
    9039             : 
    9040         796 :         if (NumEMPDMat > 0 && !state.dataHeatBal->AnyEMPD) {
    9041           0 :             ShowWarningError(state,
    9042           0 :                              format("The input file includes {} MaterialProperty:MoisturePenetrationDepth:Settings objects but the moisture "
    9043             :                                     "penetration depth algorithm is not used anywhere.",
    9044             :                                     NumEMPDMat));
    9045           0 :             msgneeded = true;
    9046             :         }
    9047         796 :         if (NumPCMat > 0 && !state.dataHeatBal->AnyCondFD) {
    9048           0 :             ShowWarningError(state,
    9049           0 :                              format("The input file includes {} MaterialProperty:PhaseChange objects but the conduction finite difference algorithm "
    9050             :                                     "is not used anywhere.",
    9051             :                                     NumPCMat));
    9052           0 :             msgneeded = true;
    9053             :         }
    9054         796 :         if (NumVTCMat > 0 && !state.dataHeatBal->AnyCondFD) {
    9055           0 :             ShowWarningError(state,
    9056           0 :                              format("The input file includes {} MaterialProperty:VariableThermalConductivity objects but the conduction finite "
    9057             :                                     "difference algorithm is not used anywhere.",
    9058             :                                     NumVTCMat));
    9059           0 :             msgneeded = true;
    9060             :         }
    9061         796 :         if (SumHAMTMat > 0 && !state.dataHeatBal->AnyHAMT) {
    9062           0 :             ShowWarningError(state,
    9063           0 :                              format("The input file includes {} MaterialProperty:HeatAndMoistureTransfer:* objects but the combined heat and "
    9064             :                                     "moisture finite difference algorithm is not used anywhere.",
    9065             :                                     SumHAMTMat));
    9066           0 :             msgneeded = true;
    9067             :         }
    9068         796 :         if (msgneeded) {
    9069           0 :             ShowContinueError(state, "Previous materials will be ignored due to HeatBalanceAlgorithm choice.");
    9070             :         }
    9071         796 :         msgneeded = false;
    9072         796 :         if (NumEMPDMat == 0 && state.dataHeatBal->AnyEMPD) {
    9073           0 :             ShowWarningError(state,
    9074             :                              "The moisture penetration depth conduction transfer function algorithm is used but the input file includes no "
    9075             :                              "MaterialProperty:MoisturePenetrationDepth:Settings objects.");
    9076           0 :             msgneeded = true;
    9077             :         }
    9078         796 :         if (SumHAMTMat == 0 && state.dataHeatBal->AnyHAMT) {
    9079           0 :             ShowWarningError(state,
    9080             :                              "The combined heat and moisture finite element algorithm is used but the input file includes no "
    9081             :                              "MaterialProperty:HeatAndMoistureTransfer:* objects.");
    9082           0 :             msgneeded = true;
    9083             :         }
    9084         796 :         if (msgneeded) {
    9085           0 :             ShowContinueError(state,
    9086             :                               "Certain materials objects are necessary to achieve proper results with the heat transfer algorithm(s) selected.");
    9087             :         }
    9088             : 
    9089             :         // Write Solution Algorithm to the initialization output file for User Verification
    9090         796 :         print(state.files.eio,
    9091             :               "{}\n",
    9092             :               "! <Surface Heat Transfer Algorithm>, Value {CTF - ConductionTransferFunction | EMPD - "
    9093             :               "MoisturePenetrationDepthConductionTransferFunction | CondFD - ConductionFiniteDifference | HAMT - "
    9094             :               "CombinedHeatAndMoistureFiniteElement} - Description,Inside Surface Max Temperature Limit{C}, Surface "
    9095             :               "Convection Coefficient Lower Limit {W/m2-K}, Surface Convection Coefficient Upper Limit {W/m2-K}");
    9096             : 
    9097         796 :         int numberOfHeatTransferAlgosUsed = 0;
    9098             :         // Formats
    9099             :         static constexpr std::string_view Format_725("Surface Heat Transfer Algorithm, {},{:.0R},{:.2R},{:.1R}\n");
    9100             : 
    9101         796 :         if (state.dataHeatBal->AnyCTF) {
    9102         782 :             constexpr std::string_view AlgoName = "CTF - ConductionTransferFunction";
    9103         782 :             ++numberOfHeatTransferAlgosUsed;
    9104         782 :             print(state.files.eio,
    9105             :                   Format_725,
    9106             :                   AlgoName,
    9107         782 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    9108         782 :                   state.dataHeatBal->LowHConvLimit,
    9109         782 :                   state.dataHeatBal->HighHConvLimit);
    9110             :         }
    9111         796 :         if (state.dataHeatBal->AnyEMPD) {
    9112           2 :             state.dataHeatBal->AllCTF = false;
    9113           2 :             constexpr std::string_view AlgoName = "EMPD - MoisturePenetrationDepthConductionTransferFunction";
    9114           2 :             ++numberOfHeatTransferAlgosUsed;
    9115           2 :             print(state.files.eio,
    9116             :                   Format_725,
    9117             :                   AlgoName,
    9118           2 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    9119           2 :                   state.dataHeatBal->LowHConvLimit,
    9120           2 :                   state.dataHeatBal->HighHConvLimit);
    9121           2 :             if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
    9122           0 :                 ShowSevereError(
    9123             :                     state,
    9124             :                     "MoisturePenetrationDepthConductionTransferFunction is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
    9125           0 :                 ErrorsFound = true;
    9126             :             }
    9127             :         }
    9128         796 :         if (state.dataHeatBal->AnyCondFD) {
    9129          12 :             state.dataHeatBal->AllCTF = false;
    9130          12 :             constexpr std::string_view AlgoName = "CondFD - ConductionFiniteDifference";
    9131          12 :             ++numberOfHeatTransferAlgosUsed;
    9132          12 :             print(state.files.eio,
    9133             :                   Format_725,
    9134             :                   AlgoName,
    9135          12 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    9136          12 :                   state.dataHeatBal->LowHConvLimit,
    9137          12 :                   state.dataHeatBal->HighHConvLimit);
    9138             :         }
    9139         796 :         if (state.dataHeatBal->AnyHAMT) {
    9140           3 :             state.dataHeatBal->AllCTF = false;
    9141           3 :             constexpr std::string_view AlgoName = "HAMT - CombinedHeatAndMoistureFiniteElement";
    9142           3 :             ++numberOfHeatTransferAlgosUsed;
    9143           3 :             print(state.files.eio,
    9144             :                   Format_725,
    9145             :                   AlgoName,
    9146           3 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    9147           3 :                   state.dataHeatBal->LowHConvLimit,
    9148           3 :                   state.dataHeatBal->HighHConvLimit);
    9149           3 :             if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
    9150           0 :                 ShowSevereError(state, "CombinedHeatAndMoistureFiniteElement is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
    9151           0 :                 ErrorsFound = true;
    9152             :             }
    9153             :         }
    9154         796 :         if (state.dataHeatBal->AnyKiva) {
    9155           9 :             state.dataHeatBal->AllCTF = false;
    9156           9 :             constexpr std::string_view AlgoName = "KivaFoundation - TwoDimensionalFiniteDifference";
    9157           9 :             ++numberOfHeatTransferAlgosUsed;
    9158           9 :             print(state.files.eio,
    9159             :                   Format_725,
    9160             :                   AlgoName,
    9161           9 :                   state.dataHeatBalSurf->MaxSurfaceTempLimit,
    9162           9 :                   state.dataHeatBal->LowHConvLimit,
    9163           9 :                   state.dataHeatBal->HighHConvLimit);
    9164             :         }
    9165             : 
    9166             :         // Check HeatTransferAlgorithm for interior surfaces
    9167         796 :         if (numberOfHeatTransferAlgosUsed > 1) {
    9168             :             int ExtSurfNum;
    9169         506 :             for (Item = 1; Item <= state.dataSurface->TotSurfaces; ++Item) {
    9170         496 :                 auto &surf = state.dataSurface->Surface(Item);
    9171         496 :                 if (surf.ExtBoundCond > 0) {
    9172         280 :                     if ((surf.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::Invalid) ||
    9173         280 :                         (surf.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::None))
    9174           0 :                         continue;
    9175         280 :                     ExtSurfNum = surf.ExtBoundCond;
    9176         280 :                     auto &extSurf = state.dataSurface->Surface(ExtSurfNum);
    9177         280 :                     if (surf.HeatTransferAlgorithm != extSurf.HeatTransferAlgorithm) {
    9178           0 :                         ShowWarningError(state,
    9179             :                                          "An interior surface is defined as two surfaces with reverse constructions. The HeatTransferAlgorithm in "
    9180             :                                          "both constructions should be same.");
    9181           0 :                         ShowContinueError(state,
    9182           0 :                                           format("The HeatTransferAlgorithm of Surface: {}, is {}",
    9183           0 :                                                  surf.Name,
    9184           0 :                                                  DataSurfaces::HeatTransAlgoStrs[static_cast<int>(surf.HeatTransferAlgorithm)]));
    9185           0 :                         ShowContinueError(state,
    9186           0 :                                           format("The HeatTransferAlgorithm of Surface: {}, is {}",
    9187           0 :                                                  extSurf.Name,
    9188           0 :                                                  DataSurfaces::HeatTransAlgoStrs[static_cast<int>(extSurf.HeatTransferAlgorithm)]));
    9189           0 :                         if (surf.HeatTransferAlgorithm > extSurf.HeatTransferAlgorithm) {
    9190           0 :                             ShowContinueError(state,
    9191           0 :                                               format("The HeatTransferAlgorithm of Surface: {}, is assigned to {}. Simulation continues.",
    9192           0 :                                                      extSurf.Name,
    9193           0 :                                                      DataSurfaces::HeatTransAlgoStrs[static_cast<int>(surf.HeatTransferAlgorithm)]));
    9194           0 :                             extSurf.HeatTransferAlgorithm = surf.HeatTransferAlgorithm;
    9195             :                         } else {
    9196           0 :                             ShowContinueError(state,
    9197           0 :                                               format("The HeatTransferAlgorithm of Surface: {}, is assigned to {}. Simulation continues.",
    9198           0 :                                                      surf.Name,
    9199           0 :                                                      DataSurfaces::HeatTransAlgoStrs[static_cast<int>(extSurf.HeatTransferAlgorithm)]));
    9200           0 :                             surf.HeatTransferAlgorithm = extSurf.HeatTransferAlgorithm;
    9201             :                         }
    9202             :                     }
    9203             :                 }
    9204             :             }
    9205             :         }
    9206             : 
    9207             :         // Assign model type to windows, shading surfaces, and TDDs
    9208       46840 :         for (Item = 1; Item <= state.dataSurface->TotSurfaces; ++Item) {
    9209       46044 :             if (state.dataSurface->Surface(Item).Class == SurfaceClass::Window || state.dataSurface->Surface(Item).Class == SurfaceClass::GlassDoor) {
    9210             :                 // todo, add complex fenestration switch  HeatTransferModel_ComplexFenestration
    9211        6217 :                 if (state.dataSurface->SurfWinWindowModelType(Item) == WindowModel::BSDF) {
    9212           0 :                     state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::ComplexFenestration;
    9213             :                 } else {
    9214        6217 :                     state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::Window5;
    9215             :                 }
    9216             :             }
    9217       46044 :             if (state.dataSurface->Surface(Item).Class == SurfaceClass::Detached_B ||
    9218       46002 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::Detached_F ||
    9219      136454 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::Shading || state.dataSurface->Surface(Item).Class == SurfaceClass::Overhang ||
    9220       44408 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::Fin) {
    9221        1636 :                 state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::None;
    9222             :             }
    9223       92088 :             if (state.dataSurface->Surface(Item).Class == SurfaceClass::TDD_Diffuser ||
    9224       46044 :                 state.dataSurface->Surface(Item).Class == SurfaceClass::TDD_Dome) {
    9225           2 :                 state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::TDD;
    9226             :             }
    9227             : 
    9228       54130 :             if (state.dataSurface->Surface(Item).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF ||
    9229        8086 :                 state.dataSurface->Surface(Item).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::EMPD) {
    9230       38001 :                 state.dataConstruction->Construct(state.dataSurface->Surface(Item).Construction).IsUsedCTF = true;
    9231             :             }
    9232             :         }
    9233         796 :     }
    9234             : 
    9235             :     struct PopCoincidentVertexReturn
    9236             :     {
    9237             :         double perimeter;
    9238             :         int poppedVertexPos = -1; // This is a STL vector position, 0-indexed
    9239             :         int keptVertexPos = -1;
    9240             :     };
    9241             : 
    9242       42201 :     PopCoincidentVertexReturn checkPopCoincidentVertex(const Array1D<Vector> &vertices)
    9243             :     {
    9244             : 
    9245       42201 :         size_t const nSides = vertices.size();
    9246             : 
    9247             :         // Pass one: Vector of distance from this vertex to the next one
    9248       42201 :         std::vector<Real64> distances(nSides);
    9249       42201 :         size_t index = 0;
    9250       42201 :         double min_distance = std::numeric_limits<Real64>::max();
    9251       42201 :         double perimeter = 0.0;
    9252      211868 :         for (auto it = vertices.begin(); it != vertices.end(); ++it) {
    9253      169667 :             auto itnext = std::next(it);
    9254      169667 :             if (itnext == std::end(vertices)) {
    9255       42201 :                 itnext = std::begin(vertices);
    9256             :             }
    9257      169667 :             const auto dist = distance(*it, *itnext);
    9258      169667 :             distances[index++] = dist;
    9259      169667 :             min_distance = std::min(min_distance, dist);
    9260      169667 :             perimeter += dist;
    9261             :         }
    9262             :         // Return early if nothing to be popped
    9263       42201 :         if (min_distance >= Constant::OneCentimeter) {
    9264       42201 :             return {perimeter};
    9265             :         }
    9266             : 
    9267             :         // Pass two: figure out the vertex that is coincident with its previous and/or next vertex and
    9268             :         // that minimizes the (distanceThisToNext + distanceThisToPrev).
    9269           0 :         Real64 min_weight = std::numeric_limits<Real64>::max();
    9270           0 :         int poppedVertexPos = -1;
    9271           0 :         int keptVertexPos = -1;
    9272             : 
    9273           0 :         for (size_t index = 0; index < nSides; ++index) {
    9274           0 :             size_t const prevIndex = (index == 0) ? nSides - 1 : index - 1;
    9275           0 :             Real64 &distanceThisToNext = distances[index];
    9276           0 :             Real64 &distanceThisToPrev = distances[prevIndex];
    9277           0 :             if ((distanceThisToNext >= Constant::OneCentimeter) && (distanceThisToPrev >= Constant::OneCentimeter)) {
    9278           0 :                 continue;
    9279             :             }
    9280           0 :             Real64 const weight = distanceThisToNext + distanceThisToPrev;
    9281           0 :             if (weight < min_weight) {
    9282           0 :                 min_weight = weight;
    9283           0 :                 poppedVertexPos = static_cast<int>(index);
    9284           0 :                 if (distanceThisToPrev < distanceThisToNext) {
    9285           0 :                     keptVertexPos = prevIndex;
    9286             :                 } else {
    9287           0 :                     keptVertexPos = static_cast<int>((index == nSides - 1) ? 0 : index + 1);
    9288             :                 }
    9289             :             }
    9290             :         }
    9291             : 
    9292             :         // Return the keptVertexPos (which can be the previous or the next), so we can print the displayExtraWarning correctly
    9293           0 :         return {perimeter, poppedVertexPos, keptVertexPos};
    9294       42201 :     }
    9295             : 
    9296       42201 :     void GetVertices(EnergyPlusData &state,
    9297             :                      int const SurfNum,             // Current surface number
    9298             :                      int const NSides,              // Number of sides to figure
    9299             :                      Array1S<Real64> const Vertices // Vertices, in specified order
    9300             :     )
    9301             :     {
    9302             : 
    9303             :         // SUBROUTINE INFORMATION:
    9304             :         //       AUTHOR         Linda Lawrie
    9305             :         //       DATE WRITTEN   May 2000
    9306             :         //       MODIFIED       na
    9307             :         //       RE-ENGINEERED  na
    9308             : 
    9309             :         // PURPOSE OF THIS SUBROUTINE:
    9310             :         // This subroutine gets the surface vertices from the arrays
    9311             :         // passed by the calling routine.  These had previously been obtained
    9312             :         // from the InputProcessor (GetObjectItem).  This routine will provide
    9313             :         // a standard place for determining various properties of the surface
    9314             :         // from the vertices.
    9315             : 
    9316             :         // METHODOLOGY EMPLOYED:
    9317             :         // na
    9318             : 
    9319             :         // REFERENCES:
    9320             :         // na
    9321             : 
    9322             :         // Using/Aliasing
    9323             :         using namespace Vectors;
    9324             : 
    9325             :         using namespace DataErrorTracking;
    9326             : 
    9327             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    9328             : 
    9329             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9330             :         static constexpr std::string_view RoutineName("GetVertices: ");
    9331             : 
    9332             :         // INTERFACE BLOCK SPECIFICATIONS
    9333             :         // na
    9334             : 
    9335             :         // DERIVED TYPE DEFINITIONS
    9336             :         // na
    9337             : 
    9338             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9339             :         int Ptr;  // Pointer into Vertice array
    9340             :         int n;    // Loop counter
    9341             :         int NSrc; // Used for CW -> CCW transformation
    9342             :         int NTar; // Used for CW -> CCW transformation
    9343             :         Real64 SurfWorldAz;
    9344             :         Real64 SurfTilt;
    9345             :         Real64 Perimeter; // Perimeter length of the surface
    9346             :         Real64 Xb;        // Intermediate calculation
    9347             :         Real64 Yb;        // Intermediate calculation
    9348             :         int ZoneNum;
    9349             :         int ThisCorner;
    9350       42201 :         std::string TiltString;
    9351             :         Real64 ThisWidth;
    9352             :         Real64 ThisHeight;
    9353             :         // unused    REAL(r64) :: ccwtest
    9354             :         // unused    LOGICAL   :: SurfaceCCW
    9355             :         Real64 dotp;
    9356             : 
    9357             :         // Object Data
    9358       42201 :         Vector const TestVector(0.0, 0.0, 1.0);
    9359       42201 :         Vector temp;
    9360             : 
    9361       42201 :         if (NSides > state.dataSurface->MaxVerticesPerSurface) state.dataSurface->MaxVerticesPerSurface = NSides;
    9362       42201 :         Ptr = 1;
    9363      211868 :         for (n = 1; n <= NSides; ++n) {
    9364      169667 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x = Vertices(Ptr);
    9365      169667 :             ++Ptr;
    9366      169667 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y = Vertices(Ptr);
    9367      169667 :             ++Ptr;
    9368      169667 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z = Vertices(Ptr);
    9369      169667 :             ++Ptr;
    9370             :         }
    9371             : 
    9372             :         // Address changing vertices if they were put in in CW order rather than CCW
    9373       42201 :         if (!state.dataSurface->CCW) {
    9374             :             // If even number of sides, this will transfer appropriately
    9375             :             // If odd number, will leave the "odd" one, which is what you want.
    9376         195 :             NSrc = NSides;
    9377         195 :             NTar = 2;
    9378         390 :             for (n = 1; n <= (NSides - 1) / 2; ++n) {
    9379         195 :                 temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc);
    9380         195 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar);
    9381         195 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar) = temp;
    9382         195 :                 --NSrc;
    9383         195 :                 ++NTar;
    9384             :             }
    9385             :         }
    9386             :         // Now address which "Corner" has been put in first.  Note: the azimuth and tilt and area
    9387             :         // calculations do not care which corner is put in first.
    9388             :         // 2/2011 - don't think the shading calculations have a corner preference.  Will keep this for
    9389             :         // consistency (for now)
    9390       42201 :         ThisCorner = state.dataSurface->Corner;
    9391       45348 :         while (ThisCorner != UpperLeftCorner) {
    9392        3147 :             if (NSides < 4) {
    9393          12 :                 if (ThisCorner == UpperRightCorner) {
    9394           0 :                     ThisCorner = UpperLeftCorner;
    9395           0 :                     break;
    9396             :                 }
    9397             :             }
    9398        3147 :             NTar = ThisCorner;
    9399        3147 :             NSrc = ThisCorner + 1;
    9400        3147 :             if (NSrc > NSides) NSrc = 1;
    9401       12860 :             for (n = 1; n <= NSides - 1; ++n) {
    9402        9713 :                 temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar);
    9403        9713 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc);
    9404        9713 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc) = temp;
    9405        9713 :                 ++NTar;
    9406        9713 :                 ++NSrc;
    9407        9713 :                 if (NTar > NSides) NTar = 1;
    9408        9713 :                 if (NSrc > NSides) NSrc = 1;
    9409             :             }
    9410        3147 :             ++ThisCorner;
    9411        3147 :             if (ThisCorner > NSides) ThisCorner = 1;
    9412             :         } // Corners
    9413       42201 :         if (!state.dataSurface->WorldCoordSystem) {
    9414             :             // Input in "relative" coordinates, use Building and Zone North Axes and Origins
    9415             :             //                                  to translate each point (including rotation for Appendix G)
    9416       33602 :             ZoneNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
    9417       33602 :             if (ZoneNum > 0) {
    9418      168443 :                 for (n = 1; n <= NSides; ++n) {
    9419      134875 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x * state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) -
    9420      134875 :                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y * state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) +
    9421      134875 :                          state.dataHeatBal->Zone(ZoneNum).OriginX;
    9422      134875 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x * state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) +
    9423      134875 :                          state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y * state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) +
    9424      134875 :                          state.dataHeatBal->Zone(ZoneNum).OriginY;
    9425      134875 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9426      134875 :                         Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    9427      134875 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9428      134875 :                         Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    9429      134875 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z += state.dataHeatBal->Zone(ZoneNum).OriginZ;
    9430             :                 }
    9431          34 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    9432          67 :                 for (n = 1; n <= NSides; ++n) {
    9433          52 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
    9434          52 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
    9435          52 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9436          52 :                         Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
    9437          52 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9438          52 :                         Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
    9439             :                 }
    9440             :             }
    9441             :         } else {
    9442             :             // if world coordinate only need to rotate for Appendix G
    9443        8599 :             ZoneNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
    9444        8599 :             if (ZoneNum > 0) {
    9445       43167 :                 for (n = 1; n <= NSides; ++n) {
    9446       34590 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
    9447       34590 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
    9448       34590 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9449       34590 :                         Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
    9450       34590 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9451       34590 :                         Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
    9452             :                 }
    9453          22 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
    9454           0 :                 for (n = 1; n <= NSides; ++n) {
    9455           0 :                     Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
    9456           0 :                     Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
    9457           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
    9458           0 :                         Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
    9459           0 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
    9460           0 :                         Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
    9461             :                 }
    9462             :             }
    9463             :         }
    9464             : 
    9465       42201 :         if (NSides > 2) {
    9466       42201 :             auto &surface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    9467       42201 :             auto &vertices = surface.Vertex;
    9468       42201 :             auto &nSides = surface.Sides;
    9469             : 
    9470             :             while (true) {
    9471       42201 :                 PopCoincidentVertexReturn const popResult = checkPopCoincidentVertex(vertices);
    9472       42201 :                 Perimeter = popResult.perimeter;
    9473       42201 :                 if (popResult.poppedVertexPos < 0) {
    9474             :                     // No pop needed, we're done
    9475       42201 :                     break;
    9476             :                 }
    9477             : 
    9478             :                 // Grab the popped one, and the kept one (regardless of whether it's previous or next)
    9479           0 :                 auto it = vertices.begin();
    9480           0 :                 std::advance(it, popResult.poppedVertexPos);
    9481           0 :                 int const poppedVertexIndex = popResult.poppedVertexPos + 1;
    9482             : 
    9483           0 :                 auto itKept = vertices.begin();
    9484           0 :                 std::advance(itKept, popResult.keptVertexPos);
    9485           0 :                 int const keptVertexIndex = popResult.keptVertexPos + 1;
    9486             : 
    9487           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
    9488           0 :                     ShowWarningError(state,
    9489           0 :                                      format("{}Distance between two vertices < .01, possibly coincident. for Surface={}, in Zone={}",
    9490             :                                             RoutineName,
    9491           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    9492           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
    9493             : 
    9494           0 :                     bool const printPoppedFirst = (poppedVertexIndex < keptVertexIndex) ? !(poppedVertexIndex == 1 && keptVertexIndex == nSides)
    9495           0 :                                                                                         : (poppedVertexIndex == nSides && keptVertexIndex == 1);
    9496             : 
    9497           0 :                     if (printPoppedFirst) {
    9498           0 :                         ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", poppedVertexIndex, it->x, it->y, it->z));
    9499           0 :                         ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", keptVertexIndex, itKept->x, itKept->y, itKept->z));
    9500             :                     } else {
    9501           0 :                         ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", keptVertexIndex, itKept->x, itKept->y, itKept->z));
    9502           0 :                         ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", poppedVertexIndex, it->x, it->y, it->z));
    9503             :                     }
    9504             :                 }
    9505           0 :                 ++state.dataErrTracking->TotalCoincidentVertices;
    9506           0 :                 if (nSides <= 3) {
    9507           0 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    9508           0 :                         ShowContinueError(state,
    9509           0 :                                           format("Cannot Drop Vertex [{}]; Number of Surface Sides at minimum. This surface is now a "
    9510             :                                                  "degenerate surface.",
    9511             :                                                  poppedVertexIndex));
    9512             :                     }
    9513           0 :                     ++state.dataErrTracking->TotalDegenerateSurfaces;
    9514             :                     // If degenerate, we won't be able to pop now nor later, so exit
    9515             :                     // mark degenerate surface?
    9516           0 :                     break;
    9517             :                 }
    9518             : 
    9519           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
    9520           0 :                     ShowContinueError(state, format("Dropping Vertex [{}].", poppedVertexIndex));
    9521             :                 }
    9522           0 :                 --nSides;
    9523           0 :                 vertices.erase(it);
    9524             :                 // No need to recompute perimeter, because it'll be done in the next iteration, until no popping or degenerate happens
    9525           0 :             }
    9526             : 
    9527       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
    9528             : 
    9529       42201 :             CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9530       42201 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9531       42201 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9532       42201 :             CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9533       42201 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9534       42201 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    9535             :             // For surfaces with subsurfaces, the following two areas are turned into net areas later by
    9536             :             // subtracting subsurface areas
    9537       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
    9538       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
    9539       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
    9540       42201 :             DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9541             :                                     SurfWorldAz,
    9542             :                                     SurfTilt,
    9543       42201 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    9544       42201 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    9545       42201 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    9546       42201 :                                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9547       42201 :             dotp = dot(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector, TestVector);
    9548       42201 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && dotp < -0.000001) {
    9549           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9550           0 :                 ShowWarningError(state,
    9551           0 :                                  format("{}Roof/Ceiling is upside down! Tilt angle=[{}], should be near 0, Surface=\"{}\", in Zone=\"{}\".",
    9552             :                                         RoutineName,
    9553             :                                         TiltString,
    9554           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    9555           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
    9556           0 :                 ShowContinueError(state, "Automatic fix is attempted.");
    9557           0 :                 ReverseAndRecalculate(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, SurfWorldAz, SurfTilt);
    9558       42201 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && SurfTilt > 80.0) {
    9559           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9560           0 :                 ShowWarningError(
    9561             :                     state,
    9562           0 :                     format("{}Roof/Ceiling is not oriented correctly! Tilt angle=[{}], should be near 0, Surface=\"{}\", in Zone=\"{}\".",
    9563             :                            RoutineName,
    9564             :                            TiltString,
    9565           0 :                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    9566           0 :                            state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
    9567             :             }
    9568       42201 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && dotp > 0.000001) {
    9569           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9570           0 :                 ShowWarningError(state,
    9571           0 :                                  format("{}Floor is upside down! Tilt angle=[{}], should be near 180, Surface=\"{}\", in Zone=\"{}\".",
    9572             :                                         RoutineName,
    9573             :                                         TiltString,
    9574           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    9575           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
    9576           0 :                 ShowContinueError(state, "Automatic fix is attempted.");
    9577           0 :                 ReverseAndRecalculate(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, SurfWorldAz, SurfTilt);
    9578       42201 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && SurfTilt < 158.2) { // slope/grade = 40%!
    9579           0 :                 TiltString = format("{:.1R}", SurfTilt);
    9580           0 :                 ShowWarningError(state,
    9581           0 :                                  format("{}Floor is not oriented correctly! Tilt angle=[{}], should be near 180, Surface=\"{}\", in Zone=\"{}\".",
    9582             :                                         RoutineName,
    9583             :                                         TiltString,
    9584           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
    9585           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
    9586             :             }
    9587       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfWorldAz;
    9588       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
    9589       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).convOrientation =
    9590       42201 :                 Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
    9591             : 
    9592             :             // Sine and cosine of azimuth and tilt
    9593       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = std::sin(SurfWorldAz * Constant::DegToRadians);
    9594       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = std::cos(SurfWorldAz * Constant::DegToRadians);
    9595       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = std::sin(SurfTilt * Constant::DegToRadians);
    9596       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = std::cos(SurfTilt * Constant::DegToRadians);
    9597       42201 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround == Constant::AutoCalculate) {
    9598       19942 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround =
    9599       19942 :                     0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9600             :             }
    9601             :             // Outward normal unit vector (pointing away from room)
    9602       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
    9603      168804 :             for (n = 1; n <= 3; ++n) {
    9604      126603 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
    9605       15855 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
    9606      126603 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
    9607       18046 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
    9608      126603 :                 if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
    9609       76068 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
    9610             :             }
    9611             : 
    9612       42201 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
    9613       78254 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
    9614       36053 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
    9615        6616 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area *= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
    9616             :             // Can perform tests on this surface here
    9617       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9618             :             // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
    9619             :             // surfaces
    9620       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
    9621       42201 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
    9622             : 
    9623             :             // Call to transform vertices
    9624             : 
    9625       42201 :             TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
    9626             : 
    9627             :         } else {
    9628           0 :             ShowFatalError(state,
    9629           0 :                            format("{}Called with less than 2 sides, Surface={}", RoutineName, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
    9630             :         }
    9631             : 
    9632             :         // Preliminary Height/Width
    9633       42201 :         temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
    9634       42201 :         ThisWidth = VecLength(temp);
    9635       42201 :         temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
    9636       42201 :         ThisHeight = VecLength(temp);
    9637       42201 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = ThisHeight;
    9638       42201 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = ThisWidth;
    9639       42201 :     }
    9640             : 
    9641           0 :     void ReverseAndRecalculate(EnergyPlusData &state,
    9642             :                                int const SurfNum,   // Surface number for the surface
    9643             :                                int const NSides,    // number of sides to surface
    9644             :                                Real64 &SurfAzimuth, // Surface Facing angle (will be 0 for roofs/floors)
    9645             :                                Real64 &SurfTilt     // Surface tilt (
    9646             :     )
    9647             :     {
    9648             : 
    9649             :         // SUBROUTINE INFORMATION:
    9650             :         //       AUTHOR         Linda Lawrie
    9651             :         //       DATE WRITTEN   February 2011
    9652             :         //       MODIFIED       na
    9653             :         //       RE-ENGINEERED  na
    9654             : 
    9655             :         // PURPOSE OF THIS SUBROUTINE:
    9656             :         // This routine reverses the vertices for a surface (needed when roof/floor is upside down)
    9657             :         // and recalculates the azimuth, etc for the surface.
    9658             : 
    9659             :         // METHODOLOGY EMPLOYED:
    9660             :         // na
    9661             : 
    9662             :         // REFERENCES:
    9663             :         // na
    9664             : 
    9665             :         // Using/Aliasing
    9666             :         using namespace Vectors;
    9667             : 
    9668             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    9669             : 
    9670             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9671             :         static constexpr std::string_view RoutineName("ReverseAndRecalculate: ");
    9672             : 
    9673             :         // INTERFACE BLOCK SPECIFICATIONS:
    9674             :         // na
    9675             : 
    9676             :         // DERIVED TYPE DEFINITIONS:
    9677             :         // na
    9678             : 
    9679             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9680             :         int n;      // Loop Control
    9681             :         int RevPtr; // pointer for reversing vertices
    9682           0 :         std::string TiltString;
    9683             : 
    9684             :         // Object Data
    9685           0 :         Array1D<Vector> Vertices(NSides); // Vertices, in specified order
    9686             : 
    9687           0 :         for (n = 1; n <= NSides; ++n) {
    9688           0 :             Vertices(n) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n);
    9689             :         }
    9690           0 :         RevPtr = NSides;
    9691           0 :         for (n = 1; n <= NSides; ++n) {
    9692           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n) = Vertices(RevPtr);
    9693           0 :             --RevPtr;
    9694             :         }
    9695             : 
    9696           0 :         print(state.files.debug, "Reversing Surface Name={}\n", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
    9697           0 :         for (n = 1; n <= NSides; ++n) {
    9698           0 :             print(state.files.debug,
    9699             :                   "side={:5} abs coord vertex= {:18.13F} {:18.13F} {:18.13F}\n",
    9700             :                   n,
    9701           0 :                   state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x,
    9702           0 :                   state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y,
    9703           0 :                   state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z);
    9704             :         }
    9705             : 
    9706           0 :         CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9707           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
    9708           0 :                                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9709           0 :         DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
    9710             :                                 SurfAzimuth,
    9711             :                                 SurfTilt,
    9712           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
    9713           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
    9714           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
    9715           0 :                                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
    9716           0 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && SurfTilt > 80.0) {
    9717           0 :             TiltString = format("{:.1R}", SurfTilt);
    9718           0 :             ShowWarningError(
    9719             :                 state,
    9720           0 :                 format("{}Roof/Ceiling is still upside down! Tilt angle=[{}], should be near 0, please fix manually.", RoutineName, TiltString));
    9721             :         }
    9722           0 :         if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && SurfTilt < 158.2) { // 40% grade!
    9723           0 :             ShowWarningError(
    9724           0 :                 state, format("{}Floor is still upside down! Tilt angle=[{}], should be near 180, please fix manually.", RoutineName, TiltString));
    9725             :         }
    9726           0 :     }
    9727             : 
    9728         818 :     void MakeMirrorSurface(EnergyPlusData &state, int &SurfNum) // In=>Surface to Mirror, Out=>new Surface index
    9729             :     {
    9730             : 
    9731             :         // SUBROUTINE INFORMATION:
    9732             :         //       AUTHOR         Linda Lawrie
    9733             :         //       DATE WRITTEN   June 2002
    9734             : 
    9735             :         // PURPOSE OF THIS SUBROUTINE:
    9736             :         // This subroutine creates a "mirror" surface using the indicated surface.
    9737             :         // This is the simple approach for bi-directional shading devices.  If, perchance,
    9738             :         // the user has already taken care of this (e.g. fins in middle of wall), there will
    9739             :         // be extra shading devices shown.
    9740             : 
    9741         818 :         auto &origSurface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
    9742         818 :         auto &newSurface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1);
    9743         818 :         newSurface = origSurface;
    9744             : 
    9745         818 :         int nVert = origSurface.Sides;
    9746             :         // Reverse the vertices in the original surface.  Add "MIR-" to name.
    9747        4068 :         for (int Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) {
    9748        3250 :             newSurface.Vertex(Vert) = origSurface.Vertex(nVert);
    9749        3250 :             --nVert;
    9750             :         }
    9751         818 :         newSurface.Name = "Mir-" + origSurface.Name;
    9752         818 :         newSurface.MirroredSurf = true;
    9753             : 
    9754         818 :         if (newSurface.Sides > 2) {
    9755         818 :             Vectors::CreateNewellAreaVector(newSurface.Vertex, newSurface.Sides, newSurface.NewellAreaVector);
    9756         818 :             newSurface.GrossArea = Vectors::VecLength(newSurface.NewellAreaVector);
    9757         818 :             newSurface.Area = newSurface.GrossArea;
    9758         818 :             newSurface.NetAreaShadowCalc = newSurface.Area;
    9759         818 :             Vectors::CreateNewellSurfaceNormalVector(newSurface.Vertex, newSurface.Sides, newSurface.NewellSurfaceNormalVector);
    9760         818 :             Real64 SurfWorldAz = 0.0;
    9761         818 :             Real64 SurfTilt = 0.0;
    9762         818 :             Vectors::DetermineAzimuthAndTilt(
    9763         818 :                 newSurface.Vertex, SurfWorldAz, SurfTilt, newSurface.lcsx, newSurface.lcsy, newSurface.lcsz, newSurface.NewellSurfaceNormalVector);
    9764         818 :             newSurface.Azimuth = SurfWorldAz;
    9765         818 :             newSurface.Tilt = SurfTilt;
    9766         818 :             newSurface.convOrientation = Convect::GetSurfConvOrientation(newSurface.Tilt);
    9767             : 
    9768             :             // Sine and cosine of azimuth and tilt
    9769         818 :             newSurface.SinAzim = std::sin(SurfWorldAz * Constant::DegToRadians);
    9770         818 :             newSurface.CosAzim = std::cos(SurfWorldAz * Constant::DegToRadians);
    9771         818 :             newSurface.SinTilt = std::sin(SurfTilt * Constant::DegToRadians);
    9772         818 :             newSurface.CosTilt = std::cos(SurfTilt * Constant::DegToRadians);
    9773             :             // Outward normal unit vector (pointing away from room)
    9774         818 :             newSurface.OutNormVec = newSurface.NewellSurfaceNormalVector;
    9775        3272 :             for (int n = 1; n <= 3; ++n) {
    9776        2454 :                 if (std::abs(newSurface.OutNormVec(n) - 1.0) < 1.e-06) newSurface.OutNormVec(n) = +1.0;
    9777        2454 :                 if (std::abs(newSurface.OutNormVec(n) + 1.0) < 1.e-06) newSurface.OutNormVec(n) = -1.0;
    9778        2454 :                 if (std::abs(newSurface.OutNormVec(n)) < 1.e-06) newSurface.OutNormVec(n) = 0.0;
    9779             :             }
    9780             : 
    9781             :             // Can perform tests on this surface here
    9782         818 :             newSurface.ViewFactorSky = 0.5 * (1.0 + newSurface.CosTilt);
    9783             :             // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing surfaces
    9784         818 :             newSurface.ViewFactorSkyIR = newSurface.ViewFactorSky;
    9785         818 :             newSurface.ViewFactorGroundIR = 0.5 * (1.0 - newSurface.CosTilt);
    9786         818 :             ++SurfNum; // Calling function expects incremented argument on return
    9787             :         }
    9788         818 :     }
    9789             : 
    9790         796 :     void GetWindowShadingControlData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    9791             :     {
    9792             : 
    9793             :         // SUBROUTINE INFORMATION:
    9794             :         //       AUTHOR         Fred Winkelmann
    9795             :         //       DATE WRITTEN   November 1998
    9796             :         //       MODIFIED       Aug 2001 (FW): add handling of new ShadingControlIsScheduled
    9797             :         //                      and GlareControlIsActive fields
    9798             :         //                      Nov 2001 (FW): add ShadingDevice as alternative to ShadedConstruction
    9799             :         //                      Dec 2001 (FW): add slat angle controls for blinds
    9800             :         //                      Aug 2002 (FW): add Setpoint2; check that specified control type is legal
    9801             :         //                      Feb 2003 (FW): add error if Material Name of Shading Device is used with
    9802             :         //                        Shading Type = BetweenGlassShade or BetweenGlassBlind
    9803             :         //                      Dec 2003 (FW): improve BetweenGlassBlind error messages
    9804             :         //                      Feb 2009 (BG): improve error checking for OnIfScheduleAllows
    9805             :         //       RE-ENGINEERED  na
    9806             : 
    9807             :         // PURPOSE OF THIS SUBROUTINE:
    9808             :         // Reads in the window shading control information
    9809             :         // from the input data file, interprets it and puts it in the derived type
    9810             : 
    9811             :         // Using/Aliasing
    9812             :         using ScheduleManager::GetScheduleIndex;
    9813             : 
    9814             :         // SUBROUTINE PARAMETER DEFINITIONS:
    9815             : 
    9816         796 :         int constexpr NumValidShadingTypes(9);
    9817             :         static Array1D_string const cValidShadingTypes(NumValidShadingTypes,
    9818             :                                                        {
    9819             :                                                            "SHADEOFF",          // 1
    9820             :                                                            "INTERIORSHADE",     // 2
    9821             :                                                            "SWITCHABLEGLAZING", // 3
    9822             :                                                            "EXTERIORSHADE",     // 4
    9823             :                                                            "EXTERIORSCREEN",    // 5
    9824             :                                                            "INTERIORBLIND",     // 6
    9825             :                                                            "EXTERIORBLIND",     // 7
    9826             :                                                            "BETWEENGLASSSHADE", // 8
    9827             :                                                            "BETWEENGLASSBLIND"  // 9
    9828         796 :                                                        });
    9829             : 
    9830         796 :         constexpr std::array<std::string_view, static_cast<int>(WindowShadingControlType::Num)> WindowShadingControlTypeNamesUC{
    9831             :             "ALWAYSON",
    9832             :             "ALWAYSOFF",
    9833             :             "ONIFSCHEDULEALLOWS",
    9834             :             "ONIFHIGHSOLARONWINDOW",
    9835             :             "ONIFHIGHHORIZONTALSOLAR",
    9836             :             "ONIFHIGHOUTDOORAIRTEMPERATURE",
    9837             :             "ONIFHIGHZONEAIRTEMPERATURE",
    9838             :             "ONIFHIGHZONECOOLING",
    9839             :             "ONIFHIGHGLARE",
    9840             :             "MEETDAYLIGHTILLUMINANCESETPOINT",
    9841             :             "ONNIGHTIFLOWOUTDOORTEMPANDOFFDAY",
    9842             :             "ONNIGHTIFLOWINSIDETEMPANDOFFDAY",
    9843             :             "ONNIGHTIFHEATINGANDOFFDAY",
    9844             :             "ONNIGHTIFLOWOUTDOORTEMPANDONDAYIFCOOLING",
    9845             :             "ONNIGHTIFHEATINGANDONDAYIFCOOLING",
    9846             :             "OFFNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW",
    9847             :             "ONNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW",
    9848             :             "ONIFHIGHOUTDOORAIRTEMPANDHIGHSOLARONWINDOW",
    9849             :             "ONIFHIGHOUTDOORAIRTEMPANDHIGHHORIZONTALSOLAR",
    9850             :             "ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW",
    9851             :             "ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR",
    9852             :             "ONIFHIGHSOLARORHIGHLUMINANCETILLMIDNIGHT",
    9853             :             "ONIFHIGHSOLARORHIGHLUMINANCETILLSUNSET",
    9854             :             "ONIFHIGHSOLARORHIGHLUMINANCETILLNEXTMORNING"};
    9855             : 
    9856         796 :         constexpr std::array<std::string_view, static_cast<int>(SlatAngleControl::Num)> SlatAngleNamesUC{
    9857             :             "FIXEDSLATANGLE", "SCHEDULEDSLATANGLE", "BLOCKBEAMSOLAR"};
    9858             : 
    9859         796 :         constexpr std::array<std::string_view, static_cast<int>(MultiSurfaceControl::Num)> MultiSurfaceControlNamesUC = {"SEQUENTIAL", "GROUP"};
    9860             : 
    9861             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9862             :         int IOStat;          // IO Status when calling get input subroutine
    9863             :         int ControlNumAlpha; // Number of control alpha names being passed
    9864             :         int ControlNumProp;  // Number of control properties being passed
    9865             :         int ControlNum;      // DO loop counter/index for window shading control number
    9866             :         int IShadedConst;    // Construction number of shaded construction
    9867             :         int IShadingDevice;  // Material number of shading device
    9868             :         int NLayers;         // Layers in shaded construction
    9869             :         bool ErrorInName;
    9870             :         bool IsBlank;
    9871             :         int Loop;
    9872             :         bool BGShadeBlindError; // True if problem with construction that is supposed to have between-glass
    9873             :         // shade or blind
    9874             :         int Found;
    9875             : 
    9876         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    9877             :         // Get the total number of window shading control blocks
    9878         796 :         cCurrentModuleObject = "WindowShadingControl";
    9879         796 :         state.dataSurface->TotWinShadingControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    9880         796 :         if (state.dataSurface->TotWinShadingControl == 0) return;
    9881             : 
    9882          43 :         state.dataSurface->WindowShadingControl.allocate(state.dataSurface->TotWinShadingControl);
    9883             : 
    9884          43 :         ControlNum = 0;
    9885         116 :         for (Loop = 1; Loop <= state.dataSurface->TotWinShadingControl; ++Loop) {
    9886             : 
    9887         146 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    9888             :                                                                      cCurrentModuleObject,
    9889             :                                                                      Loop,
    9890          73 :                                                                      state.dataIPShortCut->cAlphaArgs,
    9891             :                                                                      ControlNumAlpha,
    9892          73 :                                                                      state.dataIPShortCut->rNumericArgs,
    9893             :                                                                      ControlNumProp,
    9894             :                                                                      IOStat,
    9895          73 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    9896          73 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    9897          73 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    9898          73 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    9899             : 
    9900          73 :             ErrorInName = false;
    9901          73 :             IsBlank = false;
    9902          73 :             Util::VerifyName(state,
    9903          73 :                              state.dataIPShortCut->cAlphaArgs(1),
    9904          73 :                              state.dataSurface->WindowShadingControl,
    9905             :                              ControlNum,
    9906             :                              ErrorInName,
    9907             :                              IsBlank,
    9908         146 :                              cCurrentModuleObject + " Name");
    9909          73 :             if (ErrorInName) {
    9910           0 :                 ErrorsFound = true;
    9911           0 :                 continue;
    9912             :             }
    9913             : 
    9914          73 :             ++ControlNum;
    9915             : 
    9916          73 :             auto &windowShadingControl = state.dataSurface->WindowShadingControl(ControlNum);
    9917             : 
    9918          73 :             windowShadingControl.Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Control Name in the Derived Type
    9919             : 
    9920          73 :             windowShadingControl.ZoneIndex = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
    9921          73 :             if (windowShadingControl.ZoneIndex == 0) {
    9922           0 :                 ShowSevereError(state,
    9923           0 :                                 format("{}=\"{}\" invalid {}=\"{}\" not found.",
    9924             :                                        cCurrentModuleObject,
    9925           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    9926           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
    9927           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
    9928           0 :                 ErrorsFound = true;
    9929             :             }
    9930             : 
    9931          73 :             windowShadingControl.SequenceNumber = int(state.dataIPShortCut->rNumericArgs(1));
    9932             :             // WindowShadingControl().getInputShadedConstruction is only used during GetInput process and is ultimately stored in
    9933             :             // Surface().shadedConstructionList
    9934          73 :             windowShadingControl.getInputShadedConstruction =
    9935          73 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
    9936          73 :             windowShadingControl.ShadingDevice =
    9937          73 :                 Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(9), state.dataMaterial->Material, state.dataMaterial->TotMaterials);
    9938          73 :             windowShadingControl.Schedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
    9939          73 :             windowShadingControl.SetPoint = state.dataIPShortCut->rNumericArgs(2);
    9940          73 :             windowShadingControl.SetPoint2 = state.dataIPShortCut->rNumericArgs(3);
    9941          73 :             windowShadingControl.ShadingControlIsScheduled = getYesNoValue(state.dataIPShortCut->cAlphaArgs(7)) == BooleanSwitch::Yes;
    9942          73 :             windowShadingControl.GlareControlIsActive = getYesNoValue(state.dataIPShortCut->cAlphaArgs(8)) == BooleanSwitch::Yes;
    9943          73 :             windowShadingControl.SlatAngleSchedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
    9944             : 
    9945             :             // store the string for now and associate it after daylighting control objects are read
    9946          73 :             windowShadingControl.DaylightingControlName = state.dataIPShortCut->cAlphaArgs(12);
    9947             : 
    9948          73 :             windowShadingControl.multiSurfaceControl =
    9949          73 :                 static_cast<MultiSurfaceControl>(getEnumValue(MultiSurfaceControlNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(13))));
    9950             : 
    9951          73 :             if (windowShadingControl.multiSurfaceControl == MultiSurfaceControl::Invalid) {
    9952           0 :                 windowShadingControl.multiSurfaceControl = MultiSurfaceControl::Sequential;
    9953           0 :                 ShowWarningError(state,
    9954           0 :                                  format("{}=\"{}\" should be either SEQUENTIAL or GROUP {}=\"{}\", defaulting to \"SEQUENTIAL\"",
    9955             :                                         cCurrentModuleObject,
    9956           0 :                                         windowShadingControl.Name,
    9957           0 :                                         state.dataIPShortCut->cAlphaFieldNames(13),
    9958           0 :                                         state.dataIPShortCut->cAlphaArgs(13)));
    9959             :             }
    9960             : 
    9961          73 :             if (ControlNumAlpha >= 14) {
    9962          73 :                 windowShadingControl.FenestrationCount = ControlNumAlpha - 13;
    9963          73 :                 windowShadingControl.FenestrationName.allocate(windowShadingControl.FenestrationCount);
    9964          73 :                 windowShadingControl.FenestrationIndex.allocate(windowShadingControl.FenestrationCount);
    9965         228 :                 for (int i = 1; i <= windowShadingControl.FenestrationCount; i++) {
    9966         155 :                     windowShadingControl.FenestrationName(i) = state.dataIPShortCut->cAlphaArgs(i + 13);
    9967             :                 }
    9968             :             } else {
    9969           0 :                 ShowSevereError(state,
    9970           0 :                                 format("{}=\"{}\" invalid. Must reference at least one Fenestration Surface object name.",
    9971             :                                        cCurrentModuleObject,
    9972           0 :                                        state.dataIPShortCut->cAlphaArgs(1)));
    9973             :             }
    9974             : 
    9975          73 :             windowShadingControl.shadingControlType = static_cast<WindowShadingControlType>(
    9976          73 :                 getEnumValue(WindowShadingControlTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(5))));
    9977             : 
    9978          73 :             if (windowShadingControl.ShadingDevice > 0) {
    9979          13 :                 if (state.dataMaterial->Material(windowShadingControl.ShadingDevice)->group == Material::Group::Screen &&
    9980           0 :                     !(windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOn ||
    9981           0 :                       windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOff ||
    9982           0 :                       windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled)) {
    9983           0 :                     ErrorsFound = true;
    9984           0 :                     ShowSevereError(state,
    9985           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" for exterior screens.",
    9986             :                                            cCurrentModuleObject,
    9987           0 :                                            windowShadingControl.Name,
    9988           0 :                                            state.dataIPShortCut->cAlphaFieldNames(5),
    9989           0 :                                            state.dataIPShortCut->cAlphaArgs(5)));
    9990           0 :                     ShowContinueError(state,
    9991             :                                       "Valid shading control types for exterior window screens are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.");
    9992             :                 }
    9993             :             } else {
    9994          60 :                 if (windowShadingControl.getInputShadedConstruction > 0) {
    9995          60 :                     state.dataConstruction->Construct(windowShadingControl.getInputShadedConstruction).IsUsed = true;
    9996          60 :                     if (state.dataMaterial->Material(state.dataConstruction->Construct(windowShadingControl.getInputShadedConstruction).LayerPoint(1))
    9997          62 :                                 ->group == Material::Group::Screen &&
    9998           2 :                         !(windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOn ||
    9999           2 :                           windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOff ||
   10000           2 :                           windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled)) {
   10001           0 :                         ErrorsFound = true;
   10002           0 :                         ShowSevereError(state,
   10003           0 :                                         format("{}=\"{}\" invalid {}=\"{}\" for exterior screens.",
   10004             :                                                cCurrentModuleObject,
   10005           0 :                                                windowShadingControl.Name,
   10006           0 :                                                state.dataIPShortCut->cAlphaFieldNames(5),
   10007           0 :                                                state.dataIPShortCut->cAlphaArgs(5)));
   10008           0 :                         ShowContinueError(state,
   10009             :                                           "Valid shading control types for exterior window screens are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.");
   10010             :                     }
   10011           0 :                 } else if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
   10012           0 :                     ShowSevereError(
   10013             :                         state,
   10014           0 :                         format(
   10015           0 :                             "{}=\"{}\", {} is blank.", cCurrentModuleObject, windowShadingControl.Name, state.dataIPShortCut->cAlphaFieldNames(4)));
   10016           0 :                     ShowContinueError(state, "A valid construction is required.");
   10017           0 :                     ErrorsFound = true;
   10018             :                 } else {
   10019           0 :                     ShowSevereError(
   10020             :                         state,
   10021           0 :                         format(
   10022           0 :                             "{}=\"{}\", {} is invalid.", cCurrentModuleObject, windowShadingControl.Name, state.dataIPShortCut->cAlphaFieldNames(4)));
   10023           0 :                     ShowContinueError(state,
   10024           0 :                                       format("Construction=\"{}\" was used. A valid construction is required.", state.dataIPShortCut->cAlphaArgs(4)));
   10025           0 :                     ErrorsFound = true;
   10026             :                 }
   10027             :             }
   10028             : 
   10029             :             // Warning if setpoint is unintentionally zero
   10030          73 :             if (windowShadingControl.SetPoint == 0 && windowShadingControl.shadingControlType != WindowShadingControlType::AlwaysOn &&
   10031          33 :                 windowShadingControl.shadingControlType != WindowShadingControlType::AlwaysOff &&
   10032          33 :                 windowShadingControl.shadingControlType != WindowShadingControlType::OnIfScheduled &&
   10033          22 :                 windowShadingControl.shadingControlType != WindowShadingControlType::HiGlare) {
   10034           0 :                 ShowWarningError(state, format("{}=\"{}\", The first SetPoint is zero.", cCurrentModuleObject, windowShadingControl.Name));
   10035           0 :                 ShowContinueError(state, "..You may have forgotten to specify that setpoint.");
   10036             :             }
   10037             : 
   10038             :             // Error checks
   10039          73 :             if (state.dataIPShortCut->cAlphaArgs(7) != "YES" && state.dataIPShortCut->cAlphaArgs(7) != "NO") { // Shading Control is Schedule field
   10040           0 :                 ErrorsFound = true;
   10041           0 :                 ShowSevereError(state,
   10042           0 :                                 format("{}=\"{}\" invalid {}=\"{}\".",
   10043             :                                        cCurrentModuleObject,
   10044           0 :                                        windowShadingControl.Name,
   10045           0 :                                        state.dataIPShortCut->cAlphaFieldNames(7),
   10046           0 :                                        state.dataIPShortCut->cAlphaArgs(7)));
   10047             :             }
   10048          73 :             if (state.dataIPShortCut->cAlphaArgs(8) != "YES" && state.dataIPShortCut->cAlphaArgs(8) != "NO") { // Glare Control is Active field
   10049           0 :                 ErrorsFound = true;
   10050           0 :                 ShowSevereError(state,
   10051           0 :                                 format("{}=\"{}\" invalid {}=\"{}\".",
   10052             :                                        cCurrentModuleObject,
   10053           0 :                                        windowShadingControl.Name,
   10054           0 :                                        state.dataIPShortCut->cAlphaFieldNames(8),
   10055           0 :                                        state.dataIPShortCut->cAlphaArgs(8)));
   10056             :             }
   10057             : 
   10058          73 :             if ((windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled) &&
   10059          13 :                 (!windowShadingControl.ShadingControlIsScheduled)) { // CR 7709 BG
   10060           0 :                 ErrorsFound = true;
   10061           0 :                 ShowSevereError(state,
   10062           0 :                                 format("{} = \"{}\" invalid, {} must be set to \"Yes\" for {} = OnIfScheduleAllows",
   10063             :                                        cCurrentModuleObject,
   10064           0 :                                        windowShadingControl.Name,
   10065           0 :                                        state.dataIPShortCut->cAlphaFieldNames(7),
   10066           0 :                                        state.dataIPShortCut->cAlphaFieldNames(5)));
   10067             :             }
   10068          73 :             windowShadingControl.slatAngleControl =
   10069          73 :                 static_cast<SlatAngleControl>(getEnumValue(SlatAngleNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(10))));
   10070             : 
   10071             :             // For upward compatibility change old "noninsulating" and "insulating" shade types to
   10072             :             // INTERIORSHADE or EXTERIORSHADE
   10073         146 :             if (state.dataIPShortCut->cAlphaArgs(3) == "INTERIORNONINSULATINGSHADE" ||
   10074          73 :                 state.dataIPShortCut->cAlphaArgs(3) == "INTERIORINSULATINGSHADE") {
   10075           0 :                 ShowWarningError(state,
   10076           0 :                                  format("{}=\"{}\" is using obsolete {}=\"{}\", changing to \"InteriorShade\"",
   10077             :                                         cCurrentModuleObject,
   10078           0 :                                         windowShadingControl.Name,
   10079           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3),
   10080           0 :                                         state.dataIPShortCut->cAlphaArgs(3)));
   10081           0 :                 windowShadingControl.ShadingType = WinShadingType::IntShade;
   10082           0 :                 state.dataIPShortCut->cAlphaArgs(3) = "INTERIORSHADE";
   10083             :             }
   10084         146 :             if (state.dataIPShortCut->cAlphaArgs(3) == "EXTERIORNONINSULATINGSHADE" ||
   10085          73 :                 state.dataIPShortCut->cAlphaArgs(3) == "EXTERIORINSULATINGSHADE") {
   10086           0 :                 ShowWarningError(state,
   10087           0 :                                  format("{}=\"{}\" is using obsolete {}=\"{}\", changing to \"ExteriorShade\"",
   10088             :                                         cCurrentModuleObject,
   10089           0 :                                         windowShadingControl.Name,
   10090           0 :                                         state.dataIPShortCut->cAlphaFieldNames(3),
   10091           0 :                                         state.dataIPShortCut->cAlphaArgs(3)));
   10092           0 :                 windowShadingControl.ShadingType = WinShadingType::ExtShade;
   10093           0 :                 state.dataIPShortCut->cAlphaArgs(3) = "EXTERIORSHADE";
   10094             :             }
   10095             : 
   10096          74 :             if (windowShadingControl.shadingControlType == WindowShadingControlType::MeetDaylIlumSetp &&
   10097           1 :                 state.dataIPShortCut->cAlphaArgs(3) != "SWITCHABLEGLAZING") {
   10098           0 :                 ErrorsFound = true;
   10099           0 :                 ShowSevereError(state,
   10100           0 :                                 format("{}=\"{}\" invalid {}=\"{}\".",
   10101             :                                        cCurrentModuleObject,
   10102           0 :                                        windowShadingControl.Name,
   10103           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
   10104           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
   10105           0 :                 ShowContinueError(state,
   10106           0 :                                   format("...{} must be SwitchableGlazing for this control, but entered type=\"{}\".",
   10107           0 :                                          state.dataIPShortCut->cAlphaFieldNames(3),
   10108           0 :                                          state.dataIPShortCut->cAlphaArgs(3)));
   10109             :             }
   10110             : 
   10111             :             // Check for illegal shading type name
   10112          73 :             Found = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), cValidShadingTypes, NumValidShadingTypes);
   10113          73 :             if (Found <= 1) {
   10114           0 :                 ErrorsFound = true;
   10115           0 :                 ShowSevereError(state,
   10116           0 :                                 format("{}=\"{}\" invalid {}=\"{}\".",
   10117             :                                        cCurrentModuleObject,
   10118           0 :                                        windowShadingControl.Name,
   10119           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
   10120           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
   10121             :             } else {
   10122          73 :                 windowShadingControl.ShadingType = WinShadingType(Found);
   10123             :             }
   10124             : 
   10125          73 :             WinShadingType ShTyp = windowShadingControl.ShadingType;
   10126          73 :             IShadedConst = windowShadingControl.getInputShadedConstruction;
   10127          73 :             IShadingDevice = windowShadingControl.ShadingDevice;
   10128             : 
   10129          73 :             if (IShadedConst == 0 && IShadingDevice == 0) {
   10130           0 :                 ShowSevereError(
   10131             :                     state,
   10132           0 :                     format("{}=\"{}\" has no matching shaded construction or shading device.", cCurrentModuleObject, windowShadingControl.Name));
   10133           0 :                 ErrorsFound = true;
   10134          73 :             } else if (IShadedConst == 0 && IShadingDevice > 0) {
   10135          13 :                 if (ShTyp == WinShadingType::SwitchableGlazing) {
   10136           0 :                     ShowSevereError(state,
   10137           0 :                                     format("{}=\"{}\" has {}= SwitchableGlazing but no matching shaded construction",
   10138             :                                            cCurrentModuleObject,
   10139           0 :                                            windowShadingControl.Name,
   10140           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
   10141           0 :                     ErrorsFound = true;
   10142             :                 }
   10143          26 :                 if ((ShTyp == WinShadingType::IntShade || ShTyp == WinShadingType::ExtShade) &&
   10144          13 :                     state.dataMaterial->Material(IShadingDevice)->group != Material::Group::Shade) {
   10145           0 :                     ShowSevereError(state,
   10146           0 :                                     format("{}=\"{}\" has {}= InteriorShade or ExteriorShade but matching shading device is not a window shade",
   10147             :                                            cCurrentModuleObject,
   10148           0 :                                            windowShadingControl.Name,
   10149           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
   10150           0 :                     ShowContinueError(
   10151             :                         state,
   10152           0 :                         format("{} in error=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(8), state.dataMaterial->Material(IShadingDevice)->Name));
   10153           0 :                     ErrorsFound = true;
   10154             :                 }
   10155          13 :                 if ((ShTyp == WinShadingType::ExtScreen) && state.dataMaterial->Material(IShadingDevice)->group != Material::Group::Screen) {
   10156           0 :                     ShowSevereError(state,
   10157           0 :                                     format("{}=\"{}\" has {}= ExteriorScreen but matching shading device is not a window screen",
   10158             :                                            cCurrentModuleObject,
   10159           0 :                                            windowShadingControl.Name,
   10160           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
   10161           0 :                     ShowContinueError(
   10162             :                         state,
   10163           0 :                         format("{} in error=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(8), state.dataMaterial->Material(IShadingDevice)->Name));
   10164           0 :                     ErrorsFound = true;
   10165             :                 }
   10166          13 :                 if ((ShTyp == WinShadingType::IntBlind || ShTyp == WinShadingType::ExtBlind) &&
   10167           0 :                     state.dataMaterial->Material(IShadingDevice)->group != Material::Group::WindowBlind) {
   10168           0 :                     ShowSevereError(state,
   10169           0 :                                     format("{}=\"{}\" has {}= InteriorBlind or ExteriorBlind but matching shading device is not a window blind",
   10170             :                                            cCurrentModuleObject,
   10171           0 :                                            windowShadingControl.Name,
   10172           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
   10173           0 :                     ShowContinueError(
   10174             :                         state,
   10175           0 :                         format("{} in error=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(8), state.dataMaterial->Material(IShadingDevice)->Name));
   10176           0 :                     ErrorsFound = true;
   10177             :                 }
   10178          13 :                 if (ShTyp == WinShadingType::BGShade || ShTyp == WinShadingType::BGBlind) {
   10179           0 :                     ShowSevereError(state,
   10180           0 :                                     format("{}=\"{}\" has {}= BetweenGlassShade or BetweenGlassBlind and",
   10181             :                                            cCurrentModuleObject,
   10182           0 :                                            windowShadingControl.Name,
   10183           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
   10184           0 :                     ShowContinueError(
   10185             :                         state,
   10186           0 :                         format("{} is specified. This is illegal. Specify shaded construction instead.", state.dataIPShortCut->cAlphaFieldNames(8)));
   10187           0 :                     ErrorsFound = true;
   10188             :                 }
   10189          60 :             } else if (IShadedConst > 0 && IShadingDevice > 0) {
   10190           0 :                 IShadingDevice = 0;
   10191           0 :                 ShowWarningError(state,
   10192           0 :                                  format("{}=\"{}\" Both {} and {} are specified.",
   10193             :                                         cCurrentModuleObject,
   10194           0 :                                         windowShadingControl.Name,
   10195           0 :                                         state.dataIPShortCut->cAlphaFieldNames(4),
   10196           0 :                                         state.dataIPShortCut->cAlphaFieldNames(9)));
   10197           0 :                 ShowContinueError(state,
   10198           0 :                                   format("The {}=\"{}\" will be used.",
   10199           0 :                                          state.dataIPShortCut->cAlphaFieldNames(4),
   10200           0 :                                          state.dataConstruction->Construct(IShadedConst).Name));
   10201             :             }
   10202             : 
   10203             :             // If type = interior or exterior shade or blind require that the shaded construction
   10204             :             // have a shade layer in the correct position
   10205          73 :             if (IShadedConst != 0) {
   10206             : 
   10207          60 :                 NLayers = state.dataConstruction->Construct(IShadedConst).TotLayers;
   10208          60 :                 BGShadeBlindError = false;
   10209          60 :                 IShadingDevice = 0;
   10210          60 :                 if (state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers) != 0) {
   10211          60 :                     if (windowShadingControl.ShadingType == WinShadingType::IntShade) {
   10212          10 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers);
   10213          10 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers))->group !=
   10214             :                             Material::Group::Shade) {
   10215           0 :                             ErrorsFound = true;
   10216           0 :                             ShowSevereError(state,
   10217           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10218             :                                                    cCurrentModuleObject,
   10219           0 :                                                    windowShadingControl.Name,
   10220           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(4),
   10221           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10222           0 :                             ShowContinueError(state,
   10223           0 :                                               format("of {}=\"{}\" should have a shade layer on the inside of the window.",
   10224           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10225           0 :                                                      state.dataIPShortCut->cAlphaArgs(3)));
   10226             :                         }
   10227          50 :                     } else if (windowShadingControl.ShadingType == WinShadingType::ExtShade) {
   10228           5 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
   10229           5 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1))->group !=
   10230             :                             Material::Group::Shade) {
   10231           0 :                             ErrorsFound = true;
   10232           0 :                             ShowSevereError(state,
   10233           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10234             :                                                    cCurrentModuleObject,
   10235           0 :                                                    windowShadingControl.Name,
   10236           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(43),
   10237           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10238           0 :                             ShowContinueError(state,
   10239           0 :                                               format("of {}=\"{}\" should have a shade layer on the outside of the window.",
   10240           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10241           0 :                                                      state.dataIPShortCut->cAlphaArgs(3)));
   10242             :                         }
   10243          45 :                     } else if (windowShadingControl.ShadingType == WinShadingType::ExtScreen) {
   10244           2 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
   10245           2 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1))->group !=
   10246             :                             Material::Group::Screen) {
   10247           0 :                             ErrorsFound = true;
   10248           0 :                             ShowSevereError(state,
   10249           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10250             :                                                    cCurrentModuleObject,
   10251           0 :                                                    windowShadingControl.Name,
   10252           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(4),
   10253           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10254           0 :                             ShowContinueError(state,
   10255           0 :                                               format("of {}=\"{}\" should have a screen layer on the outside of the window.",
   10256           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10257           0 :                                                      state.dataIPShortCut->cAlphaArgs(3)));
   10258             :                         }
   10259          43 :                     } else if (windowShadingControl.ShadingType == WinShadingType::IntBlind) {
   10260          13 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers);
   10261          13 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers))->group !=
   10262             :                             Material::Group::WindowBlind) {
   10263           0 :                             ErrorsFound = true;
   10264           0 :                             ShowSevereError(state,
   10265           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10266             :                                                    cCurrentModuleObject,
   10267           0 :                                                    windowShadingControl.Name,
   10268           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(4),
   10269           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10270           0 :                             ShowContinueError(state,
   10271           0 :                                               format("of {}=\"{}\" should have a blind layer on the inside of the window.",
   10272           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10273           0 :                                                      state.dataIPShortCut->cAlphaArgs(3)));
   10274             :                         }
   10275          30 :                     } else if (windowShadingControl.ShadingType == WinShadingType::ExtBlind) {
   10276           2 :                         IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
   10277           2 :                         if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1))->group !=
   10278             :                             Material::Group::WindowBlind) {
   10279           0 :                             ErrorsFound = true;
   10280           0 :                             ShowSevereError(state,
   10281           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10282             :                                                    cCurrentModuleObject,
   10283           0 :                                                    windowShadingControl.Name,
   10284           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(4),
   10285           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10286           0 :                             ShowContinueError(state,
   10287           0 :                                               format("of {}=\"{}\" should have a blind layer on the outside of the window.",
   10288           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10289           0 :                                                      state.dataIPShortCut->cAlphaArgs(3)));
   10290             :                         }
   10291          28 :                     } else if (windowShadingControl.ShadingType == WinShadingType::BGShade) {
   10292           2 :                         if (NLayers != 5 && NLayers != 7) BGShadeBlindError = true;
   10293           2 :                         if (NLayers == 5) {
   10294           1 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(3))->group !=
   10295             :                                 Material::Group::Shade)
   10296           0 :                                 BGShadeBlindError = true;
   10297             :                         }
   10298           2 :                         if (NLayers == 7) {
   10299           1 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(5))->group !=
   10300             :                                 Material::Group::Shade)
   10301           0 :                                 BGShadeBlindError = true;
   10302             :                         }
   10303           2 :                         if (BGShadeBlindError) {
   10304           0 :                             ErrorsFound = true;
   10305           0 :                             ShowSevereError(state,
   10306           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10307             :                                                    cCurrentModuleObject,
   10308           0 :                                                    windowShadingControl.Name,
   10309           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(4),
   10310           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10311           0 :                             ShowContinueError(state,
   10312           0 :                                               format("of {}=\"{}\" should have two or three glass layers and a",
   10313           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10314           0 :                                                      state.dataIPShortCut->cAlphaArgs(32)));
   10315           0 :                             ShowContinueError(state, "between-glass shade layer with a gas layer on each side.");
   10316             :                         }
   10317          26 :                     } else if (windowShadingControl.ShadingType == WinShadingType::BGBlind) {
   10318           3 :                         if (NLayers != 5 && NLayers != 7) BGShadeBlindError = true;
   10319           3 :                         if (NLayers == 5) {
   10320           2 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(3))->group !=
   10321             :                                 Material::Group::WindowBlind)
   10322           0 :                                 BGShadeBlindError = true;
   10323             :                         }
   10324           3 :                         if (NLayers == 7) {
   10325           1 :                             if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(5))->group !=
   10326             :                                 Material::Group::WindowBlind)
   10327           0 :                                 BGShadeBlindError = true;
   10328             :                         }
   10329           3 :                         if (BGShadeBlindError) {
   10330           0 :                             ErrorsFound = true;
   10331           0 :                             ShowSevereError(state,
   10332           0 :                                             format("{}=\"{}\" the {}=\"{}\"",
   10333             :                                                    cCurrentModuleObject,
   10334           0 :                                                    windowShadingControl.Name,
   10335           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(4),
   10336           0 :                                                    state.dataIPShortCut->cAlphaArgs(4)));
   10337           0 :                             ShowContinueError(state,
   10338           0 :                                               format("of {}=\"{}\" should have two or three glass layers and a",
   10339           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(3),
   10340           0 :                                                      state.dataIPShortCut->cAlphaArgs(3)));
   10341           0 :                             ShowContinueError(state, "between-glass blind layer with a gas layer on each side.");
   10342             :                         }
   10343             :                     }
   10344             :                 }
   10345          60 :                 if (IShadingDevice > 0) {
   10346          47 :                     if ((ShTyp == WinShadingType::IntShade || ShTyp == WinShadingType::ExtShade) &&
   10347          15 :                         state.dataMaterial->Material(IShadingDevice)->group != Material::Group::Shade) {
   10348           0 :                         ShowSevereError(state,
   10349           0 :                                         format("{}=\"{}\" has {}= InteriorShade or ExteriorShade but matching shading device is not a window shade",
   10350             :                                                cCurrentModuleObject,
   10351           0 :                                                windowShadingControl.Name,
   10352           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3)));
   10353           0 :                         ShowContinueError(state, format("Shading Device in error=\"{}\".", state.dataMaterial->Material(IShadingDevice)->Name));
   10354           0 :                         ErrorsFound = true;
   10355             :                     }
   10356          32 :                     if ((ShTyp == WinShadingType::ExtScreen) && state.dataMaterial->Material(IShadingDevice)->group != Material::Group::Screen) {
   10357           0 :                         ShowSevereError(state,
   10358           0 :                                         format("{}=\"{}\" has {}= ExteriorScreen but matching shading device is not an exterior window screen.",
   10359             :                                                cCurrentModuleObject,
   10360           0 :                                                windowShadingControl.Name,
   10361           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3)));
   10362           0 :                         ShowContinueError(state, format("Shading Device in error=\"{}\".", state.dataMaterial->Material(IShadingDevice)->Name));
   10363           0 :                         ErrorsFound = true;
   10364             :                     }
   10365          47 :                     if ((ShTyp == WinShadingType::IntBlind || ShTyp == WinShadingType::ExtBlind) &&
   10366          15 :                         state.dataMaterial->Material(IShadingDevice)->group != Material::Group::WindowBlind) {
   10367           0 :                         ShowSevereError(state,
   10368           0 :                                         format("{}=\"{}\" has {}= InteriorBlind or ExteriorBlind but matching shading device is not a window blind.",
   10369             :                                                cCurrentModuleObject,
   10370           0 :                                                windowShadingControl.Name,
   10371           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3)));
   10372           0 :                         ShowContinueError(state, format("Shading Device in error=\"{}\".", state.dataMaterial->Material(IShadingDevice)->Name));
   10373           0 :                         ErrorsFound = true;
   10374             :                     }
   10375             :                 }
   10376             :             }
   10377             :         } // End of loop over window shading controls
   10378             :     }
   10379             : 
   10380        6226 :     void InitialAssociateWindowShadingControlFenestration(EnergyPlusData &state, bool &ErrorsFound, int &SurfNum)
   10381             :     {
   10382             :         // J.Glazer 2018 - operates on SurfaceTmp array before final indices are known for windows and sets the activeWindowShadingControl
   10383        7916 :         for (int iShadeCtrl = 1; iShadeCtrl <= state.dataSurface->TotWinShadingControl; ++iShadeCtrl) {
   10384        1690 :             int curShadedConstruction = state.dataSurface->WindowShadingControl(iShadeCtrl).getInputShadedConstruction;
   10385        6672 :             for (int jFeneRef = 1; jFeneRef <= state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationCount; ++jFeneRef) {
   10386        4982 :                 if (Util::SameString(state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationName(jFeneRef),
   10387        4982 :                                      state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) {
   10388         155 :                     state.dataGlobal->AndShadingControlInModel = true;
   10389         155 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = true;
   10390         155 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.push_back(iShadeCtrl);
   10391         155 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = iShadeCtrl;
   10392         155 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.push_back(curShadedConstruction);
   10393         155 :                     state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = curShadedConstruction;
   10394             : 
   10395             :                     // check to make the window refenced is an exterior window
   10396         155 :                     if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment) {
   10397           0 :                         ErrorsFound = true;
   10398           0 :                         ShowSevereError(
   10399             :                             state,
   10400           0 :                             format("InitialAssociateWindowShadingControlFenestration: \"{}\", invalid  because it is not an exterior window.",
   10401           0 :                                    state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
   10402           0 :                         ShowContinueError(
   10403             :                             state,
   10404           0 :                             format(".. It appears on WindowShadingControl object: \"{}", state.dataSurface->WindowShadingControl(iShadeCtrl).Name));
   10405             :                     }
   10406             :                     // check to make sure the window is not using equivalent layer window construction
   10407         155 :                     if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
   10408           0 :                         ErrorsFound = true;
   10409           0 :                         ShowSevereError(state,
   10410           0 :                                         format("InitialAssociateWindowShadingControlFenestration: =\"{}\", invalid \".",
   10411           0 :                                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
   10412           0 :                         ShowContinueError(state, ".. equivalent layer window model does not use shading control object.");
   10413           0 :                         ShowContinueError(state, ".. Shading control is set to none or zero, and simulation continues.");
   10414           0 :                         ShowContinueError(
   10415             :                             state,
   10416           0 :                             format(".. It appears on WindowShadingControl object: \"{}", state.dataSurface->WindowShadingControl(iShadeCtrl).Name));
   10417           0 :                         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
   10418             :                     }
   10419             :                 }
   10420             :             }
   10421             :         }
   10422        6226 :     }
   10423             : 
   10424       46044 :     void FinalAssociateWindowShadingControlFenestration(EnergyPlusData &state, bool &ErrorsFound)
   10425             :     {
   10426             :         // J.Glazer 2018 - operates on Surface array after final indices are known for windows and checks to make sure it is correct
   10427       53724 :         for (int iShadeCtrl = 1; iShadeCtrl <= state.dataSurface->TotWinShadingControl; ++iShadeCtrl) {
   10428       25887 :             for (int jFeneRef = 1; jFeneRef <= state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationCount; ++jFeneRef) {
   10429       18207 :                 int fenestrationIndex = Util::FindItemInList(state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationName(jFeneRef),
   10430       18207 :                                                              state.dataSurface->Surface,
   10431       18207 :                                                              state.dataSurface->TotSurfaces);
   10432       36414 :                 if (std::find(state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.begin(),
   10433       36414 :                               state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.end(),
   10434       54621 :                               iShadeCtrl) != state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.end()) {
   10435       18207 :                     state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationIndex(jFeneRef) = fenestrationIndex;
   10436             :                 } else {
   10437             :                     // this error condition should not occur since the rearrangement of Surface() from SurfureTmp() is reliable.
   10438           0 :                     ErrorsFound = true;
   10439           0 :                     ShowSevereError(state,
   10440           0 :                                     format("FinalAssociateWindowShadingControlFenestration: Fenestration surface named \"{}\" has "
   10441             :                                            "WindowShadingContol index that does not match the initial index assigned.",
   10442           0 :                                            state.dataSurface->Surface(fenestrationIndex).Name));
   10443           0 :                     ShowContinueError(state,
   10444           0 :                                       format("This occurs while WindowShadingControl object: \"{}\" is being evaluated. ",
   10445           0 :                                              state.dataSurface->WindowShadingControl(iShadeCtrl).Name));
   10446             :                 }
   10447             :             }
   10448             :         }
   10449       46044 :     }
   10450             : 
   10451       46044 :     void CheckWindowShadingControlSimilarForWindow(EnergyPlusData &state, bool &ErrorsFound)
   10452             :     {
   10453             :         // For each window check if all window shading controls on list are the same except for name, schedule name, construction, and
   10454             :         // material
   10455    12259950 :         for (auto &theSurf : state.dataSurface->Surface) {
   10456    12213906 :             if (theSurf.HasShadeControl) {
   10457       18067 :                 if (theSurf.windowShadingControlList.size() > 1) {
   10458         140 :                     int firstWindowShadingControl = theSurf.windowShadingControlList.front();
   10459         420 :                     for (auto wsc = std::next(theSurf.windowShadingControlList.begin()); wsc != theSurf.windowShadingControlList.end(); ++wsc) {
   10460         140 :                         if (!isWindowShadingControlSimilar(state, firstWindowShadingControl, *wsc)) {
   10461           0 :                             ErrorsFound = true;
   10462           0 :                             ShowSevereError(state,
   10463           0 :                                             format("CheckWindowShadingControlSimilarForWindow: Fenestration surface named \"{}\" has multiple "
   10464             :                                                    "WindowShadingContols that are not similar.",
   10465           0 :                                                    theSurf.Name));
   10466           0 :                             ShowContinueError(state,
   10467           0 :                                               format("for: \"{} and: {}",
   10468           0 :                                                      state.dataSurface->WindowShadingControl(firstWindowShadingControl).Name,
   10469           0 :                                                      state.dataSurface->WindowShadingControl(*wsc).Name));
   10470             :                         }
   10471         140 :                     }
   10472             :                 }
   10473             :             }
   10474       46044 :         }
   10475       46044 :     }
   10476             : 
   10477         140 :     bool isWindowShadingControlSimilar(EnergyPlusData &state, int a, int b)
   10478             :     {
   10479             :         // Compares two window shading controls are the same except for the name, schedule name, construction, and material
   10480         140 :         auto &WindowShadingControlA = state.dataSurface->WindowShadingControl(a);
   10481         140 :         auto &WindowShadingControlB = state.dataSurface->WindowShadingControl(b);
   10482         280 :         return (WindowShadingControlA.ZoneIndex == WindowShadingControlB.ZoneIndex &&
   10483         140 :                 WindowShadingControlA.ShadingType == WindowShadingControlB.ShadingType &&
   10484         140 :                 WindowShadingControlA.shadingControlType == WindowShadingControlB.shadingControlType &&
   10485         140 :                 WindowShadingControlA.SetPoint == WindowShadingControlB.SetPoint &&
   10486         140 :                 WindowShadingControlA.ShadingControlIsScheduled == WindowShadingControlB.ShadingControlIsScheduled &&
   10487         140 :                 WindowShadingControlA.GlareControlIsActive == WindowShadingControlB.GlareControlIsActive &&
   10488         140 :                 WindowShadingControlA.slatAngleControl == WindowShadingControlB.slatAngleControl &&
   10489         280 :                 WindowShadingControlA.SetPoint2 == WindowShadingControlB.SetPoint2 &&
   10490         140 :                 WindowShadingControlA.DaylightingControlName == WindowShadingControlB.DaylightingControlName &&
   10491         420 :                 WindowShadingControlA.DaylightControlIndex == WindowShadingControlB.DaylightControlIndex &&
   10492         280 :                 WindowShadingControlA.multiSurfaceControl == WindowShadingControlB.multiSurfaceControl);
   10493             :     }
   10494             : 
   10495         796 :     void GetStormWindowData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
   10496             :     {
   10497             : 
   10498             :         // SUBROUTINE INFORMATION:
   10499             :         //       AUTHOR         Fred Winkelmann
   10500             :         //       DATE WRITTEN   December 2003
   10501             :         //       MODIFIED       na
   10502             : 
   10503             :         //       RE-ENGINEERED  na
   10504             : 
   10505             :         // PURPOSE OF THIS SUBROUTINE:
   10506             :         // Reads in the storm window data from the input file,
   10507             :         // interprets it and puts it in the derived type
   10508             : 
   10509             :         // Using/Aliasing
   10510             : 
   10511             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   10512             : 
   10513             :         int IOStat;           // IO Status when calling get input subroutine
   10514             :         int StormWinNumAlpha; // Number of alpha names being passed
   10515             :         int StormWinNumProp;  // Number of properties being passed
   10516             :         int StormWinNum;      // Index for storm window number
   10517             :         int loop;             // Do loop counter
   10518             :         int SurfNum;          // Surface number
   10519             :         int MatNum;           // Material number
   10520             : 
   10521         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   10522             : 
   10523             :         // Get the total number of storm window input objects
   10524         796 :         cCurrentModuleObject = "WindowProperty:StormWindow";
   10525         796 :         state.dataSurface->TotStormWin = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   10526         796 :         if (state.dataSurface->TotStormWin == 0) return;
   10527             : 
   10528           1 :         state.dataSurface->StormWindow.allocate(state.dataSurface->TotStormWin);
   10529             : 
   10530           1 :         StormWinNum = 0;
   10531           1 :         for (loop = 1; loop <= state.dataSurface->TotStormWin; ++loop) {
   10532             : 
   10533           2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   10534             :                                                                      cCurrentModuleObject,
   10535             :                                                                      loop,
   10536           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
   10537             :                                                                      StormWinNumAlpha,
   10538           1 :                                                                      state.dataIPShortCut->rNumericArgs,
   10539             :                                                                      StormWinNumProp,
   10540             :                                                                      IOStat,
   10541           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   10542           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   10543           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   10544           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   10545           1 :             ++StormWinNum;
   10546           1 :             state.dataSurface->StormWindow(StormWinNum).BaseWindowNum =
   10547           1 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
   10548           1 :             state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum =
   10549           1 :                 Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(2), state.dataMaterial->Material, state.dataMaterial->TotMaterials);
   10550           1 :             state.dataSurface->StormWindow(StormWinNum).StormWinDistance = state.dataIPShortCut->rNumericArgs(1);
   10551           1 :             state.dataSurface->StormWindow(StormWinNum).MonthOn = state.dataIPShortCut->rNumericArgs(2);
   10552           1 :             state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn = state.dataIPShortCut->rNumericArgs(3);
   10553           1 :             state.dataSurface->StormWindow(StormWinNum).DateOn =
   10554           1 :                 General::OrdinalDay(state.dataSurface->StormWindow(StormWinNum).MonthOn, state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn, 1);
   10555           1 :             state.dataSurface->StormWindow(StormWinNum).MonthOff = state.dataIPShortCut->rNumericArgs(4);
   10556           1 :             state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff = state.dataIPShortCut->rNumericArgs(5);
   10557           1 :             state.dataSurface->StormWindow(StormWinNum).DateOff = General::OrdinalDay(
   10558           1 :                 state.dataSurface->StormWindow(StormWinNum).MonthOff, state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff, 1);
   10559             : 
   10560           1 :             if (state.dataSurface->StormWindow(StormWinNum).DateOn == state.dataSurface->StormWindow(StormWinNum).DateOff) {
   10561           0 :                 ShowSevereError(state,
   10562           0 :                                 format("{}: Date On = Date Off -- not allowed, occurred in WindowProperty:StormWindow Input #{}",
   10563             :                                        cCurrentModuleObject,
   10564             :                                        StormWinNum));
   10565           0 :                 ErrorsFound = true;
   10566             :             }
   10567             : 
   10568             :             enum Month
   10569             :             {
   10570             :                 January = 1,
   10571             :                 February,
   10572             :                 March,
   10573             :                 April,
   10574             :                 May,
   10575             :                 June,
   10576             :                 July,
   10577             :                 August,
   10578             :                 September,
   10579             :                 October,
   10580             :                 November,
   10581             :                 December
   10582             :             };
   10583           1 :             constexpr std::array<int, 13> oneBasedDaysInMonth = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   10584             : 
   10585           1 :             int const monthOn = state.dataSurface->StormWindow(StormWinNum).MonthOn;
   10586           1 :             if (monthOn >= January && monthOn <= December) {
   10587           2 :                 if (state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn >
   10588           1 :                     oneBasedDaysInMonth[state.dataSurface->StormWindow(StormWinNum).MonthOn]) {
   10589           0 :                     ShowSevereError(state,
   10590           0 :                                     format("{}: Date On (Day of Month) [{}], invalid for WindowProperty:StormWindow Input #{}",
   10591             :                                            cCurrentModuleObject,
   10592           0 :                                            state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn,
   10593             :                                            StormWinNum));
   10594           0 :                     ErrorsFound = true;
   10595             :                 }
   10596           1 :                 break;
   10597             :             } else {
   10598           0 :                 ShowSevereError(state,
   10599           0 :                                 format("{}: Date On Month [{}], invalid for WindowProperty:StormWindow Input #{}",
   10600             :                                        cCurrentModuleObject,
   10601           0 :                                        state.dataSurface->StormWindow(StormWinNum).MonthOn,
   10602             :                                        StormWinNum));
   10603           0 :                 ErrorsFound = true;
   10604             :             }
   10605             : 
   10606           0 :             int const monthOff = state.dataSurface->StormWindow(StormWinNum).MonthOff;
   10607           0 :             if (monthOff >= January && monthOff <= December) {
   10608           0 :                 if (state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff >
   10609           0 :                     oneBasedDaysInMonth[state.dataSurface->StormWindow(StormWinNum).MonthOff]) {
   10610           0 :                     ShowSevereError(state,
   10611           0 :                                     format("{}: Date Off (Day of Month) [{}], invalid for WindowProperty:StormWindow Input #{}",
   10612             :                                            cCurrentModuleObject,
   10613           0 :                                            state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff,
   10614             :                                            StormWinNum));
   10615           0 :                     ErrorsFound = true;
   10616             :                 }
   10617           0 :                 break;
   10618             :             } else {
   10619           0 :                 ShowSevereError(state,
   10620           0 :                                 format("{}: Date Off Month [{}], invalid for WindowProperty:StormWindow Input #{}",
   10621             :                                        cCurrentModuleObject,
   10622           0 :                                        state.dataSurface->StormWindow(StormWinNum).MonthOff,
   10623             :                                        StormWinNum));
   10624           0 :                 ErrorsFound = true;
   10625             :             }
   10626             :         }
   10627             : 
   10628             :         // Error checks
   10629             : 
   10630           2 :         for (StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
   10631             :             // Require BaseWindowNum be that of an exterior window
   10632           1 :             SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum;
   10633           1 :             if (SurfNum == 0) {
   10634           0 :                 ShowSevereError(state, format("{}=\"{}\" invalid.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   10635           0 :                 ErrorsFound = true;
   10636             :             } else {
   10637           1 :                 auto const &surf = state.dataSurface->Surface(SurfNum);
   10638           1 :                 if (surf.Class != SurfaceClass::Window || surf.ExtBoundCond != 0) {
   10639           0 :                     ShowSevereError(state, format("{}=\"{}\"", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   10640           0 :                     ShowContinueError(state, format("cannot be used with surface={}", surf.Name));
   10641           0 :                     ShowContinueError(state, "because that surface is not an exterior window.");
   10642           0 :                     ErrorsFound = true;
   10643             :                 }
   10644             :             }
   10645             : 
   10646             :             // Require that storm window material be glass
   10647           1 :             MatNum = state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum;
   10648           1 :             if (SurfNum > 0) {
   10649           1 :                 if (MatNum == 0) {
   10650           0 :                     ShowSevereError(state, format("{}=\"{}\"", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   10651           0 :                     ShowContinueError(state,
   10652           0 :                                       format("{}=\"{}\" not found as storm window layer.",
   10653           0 :                                              state.dataIPShortCut->cAlphaFieldNames(2),
   10654           0 :                                              state.dataIPShortCut->cAlphaArgs(2)));
   10655           0 :                     ErrorsFound = true;
   10656             :                 } else {
   10657           1 :                     if (state.dataMaterial->Material(MatNum)->group != Material::Group::WindowGlass) {
   10658           0 :                         ShowSevereError(state, format("{}=\"{}\"", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   10659           0 :                         ShowContinueError(state,
   10660           0 :                                           format("{}=\"{}must be a WindowMaterial:Glazing or WindowMaterial:Glazing:RefractionExtinctionMethod",
   10661           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(2),
   10662           0 :                                                  state.dataIPShortCut->cAlphaArgs(2)));
   10663           0 :                         ErrorsFound = true;
   10664             :                     }
   10665             :                 }
   10666             :             }
   10667             : 
   10668             :             // Error if base window has airflow control
   10669           1 :             if (SurfNum > 0) {
   10670           1 :                 if (state.dataSurface->SurfWinAirflowControlType(SurfNum) != DataSurfaces::WindowAirFlowControlType::Invalid) {
   10671           0 :                     ShowSevereError(
   10672             :                         state,
   10673           0 :                         format("{}=\"{} cannot be used because it is an airflow window (i.e., has WindowProperty:AirflowControl specified)",
   10674             :                                cCurrentModuleObject,
   10675           0 :                                state.dataIPShortCut->cAlphaArgs(1)));
   10676           0 :                     ErrorsFound = true;
   10677             :                 }
   10678             :             }
   10679             : 
   10680             :             // Check for reversal of on and off times
   10681           1 :             if (SurfNum > 0) {
   10682           1 :                 if ((state.dataEnvrn->Latitude > 0.0 &&
   10683           2 :                      (state.dataSurface->StormWindow(StormWinNum).MonthOn < state.dataSurface->StormWindow(StormWinNum).MonthOff)) ||
   10684           1 :                     (state.dataEnvrn->Latitude <= 0.0 &&
   10685           0 :                      (state.dataSurface->StormWindow(StormWinNum).MonthOn > state.dataSurface->StormWindow(StormWinNum).MonthOff))) {
   10686           0 :                     ShowWarningError(state,
   10687           0 :                                      format("{}=\"{}\" check times that storm window", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   10688           0 :                     ShowContinueError(state,
   10689           0 :                                       format("is put on (month={}, day={}) and taken off (month={}, day={});",
   10690           0 :                                              state.dataSurface->StormWindow(StormWinNum).MonthOn,
   10691           0 :                                              state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn,
   10692           0 :                                              state.dataSurface->StormWindow(StormWinNum).MonthOff,
   10693           0 :                                              state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff));
   10694           0 :                     ShowContinueError(state, format("these times may be reversed for your building latitude={:.2R} deg.", state.dataEnvrn->Latitude));
   10695             :                 }
   10696             :             }
   10697             :         }
   10698             :     }
   10699             : 
   10700         796 :     void GetWindowGapAirflowControlData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
   10701             :     {
   10702             : 
   10703             :         // SUBROUTINE INFORMATION:
   10704             :         //       AUTHOR         Fred Winkelmann
   10705             :         //       DATE WRITTEN   Feb 2003
   10706             :         //       MODIFIED       June 2003, FCW: add destination = return air;
   10707             :         //                        more error messages
   10708             :         //       RE-ENGINEERED  na
   10709             : 
   10710             :         // PURPOSE OF THIS SUBROUTINE:
   10711             :         // Reads in the window airflow control information from the input data file,
   10712             :         // interprets it and puts it in the SurfaceWindow derived type
   10713             : 
   10714             :         // Using/Aliasing
   10715             :         using ScheduleManager::GetScheduleIndex;
   10716             : 
   10717             :         static constexpr std::string_view RoutineName("GetWindowGapAirflowControlData");
   10718             :         int IOStat;               // IO Status when calling get input subroutine
   10719             :         int ControlNumAlpha;      // Number of control alpha names being passed
   10720             :         int ControlNumProp;       // Number of control properties being passed
   10721             :         int TotWinAirflowControl; // Total window airflow control statements
   10722             :         bool WrongSurfaceType;    // True if associated surface is not 2- or 3-pane exterior window
   10723             :         int Loop;
   10724             :         int SurfNum;      // Surface number
   10725         796 :         int ConstrNum(0); // Construction number
   10726             :         int ConstrNumSh;  // Shaded Construction number
   10727             :         int MatGapFlow;   // Material number of gas in airflow gap of window's construction
   10728             :         int MatGapFlow1;  // Material number of gas on either side of a between-glass shade/blind
   10729             :         int MatGapFlow2;
   10730             : 
   10731         796 :         constexpr std::array<std::string_view, static_cast<int>(WindowAirFlowSource::Num)> WindowAirFlowSourceNamesUC{"INDOORAIR", "OUTDOORAIR"};
   10732         796 :         constexpr std::array<std::string_view, static_cast<int>(WindowAirFlowDestination::Num)> WindowAirFlowDestinationNamesUC{
   10733             :             "INDOORAIR", "OUTDOORAIR", "RETURNAIR"};
   10734             : 
   10735             :         // of the shaded construction of airflow window
   10736         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   10737             :         // Get the total number of window airflow control statements
   10738         796 :         cCurrentModuleObject = "WindowProperty:AirflowControl";
   10739         796 :         TotWinAirflowControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   10740         796 :         if (TotWinAirflowControl == 0) return;
   10741             : 
   10742          10 :         for (Loop = 1; Loop <= TotWinAirflowControl; ++Loop) { // Loop through all surfaces in the input...
   10743             : 
   10744          16 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   10745             :                                                                      cCurrentModuleObject,
   10746             :                                                                      Loop,
   10747           8 :                                                                      state.dataIPShortCut->cAlphaArgs,
   10748             :                                                                      ControlNumAlpha,
   10749           8 :                                                                      state.dataIPShortCut->rNumericArgs,
   10750             :                                                                      ControlNumProp,
   10751             :                                                                      IOStat,
   10752           8 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   10753           8 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   10754           8 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   10755           8 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   10756             : 
   10757           8 :             SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
   10758           8 :             if (SurfNum == 0) {
   10759           0 :                 ShowSevereError(state, format("{}=\"{}\" not found.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   10760           0 :                 ErrorsFound = true;
   10761             :             }
   10762             :             // Check that associated surface is a 2- or 3-pane exterior window
   10763           8 :             WrongSurfaceType = false;
   10764           8 :             if (SurfNum != 0) {
   10765           8 :                 auto const &surf = state.dataSurface->Surface(SurfNum);
   10766           8 :                 if (surf.Class != SurfaceClass::Window) WrongSurfaceType = true;
   10767           8 :                 if (surf.Class == SurfaceClass::Window) {
   10768           8 :                     ConstrNum = surf.Construction;
   10769          12 :                     if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers != 2 &&
   10770           4 :                         state.dataConstruction->Construct(ConstrNum).TotGlassLayers != 3)
   10771           0 :                         WrongSurfaceType = true;
   10772           8 :                     if (surf.ExtBoundCond != ExternalEnvironment) WrongSurfaceType = true;
   10773             :                 }
   10774           8 :                 if (WrongSurfaceType) {
   10775           0 :                     ShowSevereError(state,
   10776           0 :                                     format("{}=\"{}\" is not an exterior window with 2 or 3 glass layers.",
   10777             :                                            cCurrentModuleObject,
   10778           0 :                                            state.dataIPShortCut->cAlphaArgs(1)));
   10779           0 :                     ErrorsFound = true;
   10780             :                 }
   10781             :             }
   10782             : 
   10783             :             // Error if illegal airflow source
   10784           8 :             if (state.dataIPShortCut->cAlphaArgs(2) != "INDOORAIR" && state.dataIPShortCut->cAlphaArgs(2) != "OUTDOORAIR") {
   10785           0 :                 ErrorsFound = true;
   10786           0 :                 ShowSevereError(state,
   10787           0 :                                 format("{}=\"{}\" invalid {}=\"{}\"",
   10788             :                                        cCurrentModuleObject,
   10789           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
   10790           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
   10791           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
   10792             :             }
   10793             : 
   10794             :             // Error if illegal airflow destination
   10795           8 :             if (state.dataIPShortCut->cAlphaArgs(3) != "INDOORAIR" && state.dataIPShortCut->cAlphaArgs(3) != "OUTDOORAIR" &&
   10796           0 :                 state.dataIPShortCut->cAlphaArgs(3) != "RETURNAIR") {
   10797           0 :                 ErrorsFound = true;
   10798           0 :                 ShowSevereError(state,
   10799           0 :                                 format("{}=\"{}\" invalid {}=\"{}\"",
   10800             :                                        cCurrentModuleObject,
   10801           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
   10802           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
   10803           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
   10804             :             }
   10805             : 
   10806             :             // Error if source = OutsideAir and destination = ReturnAir
   10807           8 :             if (state.dataIPShortCut->cAlphaArgs(2) == "OUTDOORAIR" && state.dataIPShortCut->cAlphaArgs(3) == "RETURNAIR") {
   10808           0 :                 ErrorsFound = true;
   10809           0 :                 ShowSevereError(state,
   10810           0 :                                 format("{}=\"{}\" invalid {}=\"{}\"",
   10811             :                                        cCurrentModuleObject,
   10812           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
   10813           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
   10814           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
   10815           0 :                 ShowContinueError(state, format("..when {}=\"{}\"", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
   10816             :             }
   10817             : 
   10818             :             // Error if illegal airflow control type
   10819           8 :             if (state.dataIPShortCut->cAlphaArgs(4) != "ALWAYSONATMAXIMUMFLOW" && state.dataIPShortCut->cAlphaArgs(4) != "ALWAYSOFF" &&
   10820           0 :                 state.dataIPShortCut->cAlphaArgs(4) != "SCHEDULEDONLY") {
   10821           0 :                 ErrorsFound = true;
   10822           0 :                 ShowSevereError(state,
   10823           0 :                                 format("{}=\"{}\" invalid {}=\"{}\"",
   10824             :                                        cCurrentModuleObject,
   10825           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
   10826           0 :                                        state.dataIPShortCut->cAlphaFieldNames(4),
   10827           0 :                                        state.dataIPShortCut->cAlphaArgs(4)));
   10828             :             }
   10829             : 
   10830             :             // Error if illegal value for Airflow Has Multiplier Schedule
   10831           8 :             if (state.dataIPShortCut->cAlphaArgs(5) != "YES" && state.dataIPShortCut->cAlphaArgs(5) != "NO") {
   10832           0 :                 ErrorsFound = true;
   10833           0 :                 ShowSevereError(state,
   10834           0 :                                 format("{}=\"{}\" invalid {}=\"{}\"",
   10835             :                                        cCurrentModuleObject,
   10836           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
   10837           0 :                                        state.dataIPShortCut->cAlphaFieldNames(5),
   10838           0 :                                        state.dataIPShortCut->cAlphaArgs(5)));
   10839             :             }
   10840             : 
   10841             :             // Error if Airflow Control Type = ScheduledOnly and Airflow Has Multiplier Schedule = No
   10842           8 :             if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULEDONLY" && state.dataIPShortCut->cAlphaArgs(5) == "NO") {
   10843           0 :                 ErrorsFound = true;
   10844           0 :                 ShowSevereError(state,
   10845           0 :                                 format("{}=\"{}\" invalid {}=\"{}\"",
   10846             :                                        cCurrentModuleObject,
   10847           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
   10848           0 :                                        state.dataIPShortCut->cAlphaFieldNames(4),
   10849           0 :                                        state.dataIPShortCut->cAlphaArgs(4)));
   10850           0 :                 ShowContinueError(state, format("..when {}=\"{}\"", state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5)));
   10851             :             }
   10852             : 
   10853             :             // Warning if Airflow Control Type = AlwaysOnAtMaxFlow and Airflow Has Multiplier Schedule = Yes
   10854           8 :             if (state.dataIPShortCut->cAlphaArgs(4) == "ALWAYSONATMAXIMUMFLOW" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
   10855           0 :                 ShowWarningError(state,
   10856           0 :                                  format("{}=\"{}has {}=\"{}\"",
   10857             :                                         cCurrentModuleObject,
   10858           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
   10859           0 :                                         state.dataIPShortCut->cAlphaFieldNames(4),
   10860           0 :                                         state.dataIPShortCut->cAlphaArgs(4)));
   10861           0 :                 ShowContinueError(state,
   10862           0 :                                   format("..but {}=\"{}If specified, the {} will be ignored.",
   10863           0 :                                          state.dataIPShortCut->cAlphaFieldNames(5),
   10864           0 :                                          state.dataIPShortCut->cAlphaArgs(5),
   10865           0 :                                          state.dataIPShortCut->cAlphaFieldNames(5)));
   10866             :             }
   10867             : 
   10868             :             // Warning if Airflow Control Type = AlwaysOff and Airflow Has Multiplier Schedule = Yes
   10869           8 :             if (state.dataIPShortCut->cAlphaArgs(4) == "ALWAYSOFF" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
   10870           0 :                 ShowWarningError(state,
   10871           0 :                                  format("{}=\"{}has {}=\"{}\"",
   10872             :                                         cCurrentModuleObject,
   10873           0 :                                         state.dataIPShortCut->cAlphaArgs(1),
   10874           0 :                                         state.dataIPShortCut->cAlphaFieldNames(4),
   10875           0 :                                         state.dataIPShortCut->cAlphaArgs(4)));
   10876           0 :                 ShowContinueError(state,
   10877           0 :                                   format("..but {}=\"{}\". If specified, the {} will be ignored.",
   10878           0 :                                          state.dataIPShortCut->cAlphaFieldNames(5),
   10879           0 :                                          state.dataIPShortCut->cAlphaArgs(5),
   10880           0 :                                          state.dataIPShortCut->cAlphaFieldNames(5)));
   10881             :             }
   10882             : 
   10883           8 :             if (SurfNum > 0) {
   10884           8 :                 auto const &surf = state.dataSurface->Surface(SurfNum);
   10885           8 :                 state.dataSurface->AirflowWindows = true;
   10886           8 :                 state.dataSurface->SurfWinAirflowSource(SurfNum) =
   10887           8 :                     static_cast<WindowAirFlowSource>(getEnumValue(WindowAirFlowSourceNamesUC, state.dataIPShortCut->cAlphaArgs(2)));
   10888             : 
   10889           8 :                 state.dataSurface->SurfWinAirflowDestination(SurfNum) =
   10890           8 :                     static_cast<WindowAirFlowDestination>(getEnumValue(WindowAirFlowDestinationNamesUC, state.dataIPShortCut->cAlphaArgs(3)));
   10891             : 
   10892           8 :                 if (state.dataSurface->SurfWinAirflowDestination(SurfNum) == WindowAirFlowDestination::Return) {
   10893           0 :                     int controlledZoneNum = DataZoneEquipment::GetControlledZoneIndex(state, surf.ZoneName);
   10894           0 :                     if (controlledZoneNum > 0) {
   10895           0 :                         state.dataHeatBal->Zone(surf.Zone).HasAirFlowWindowReturn = true;
   10896             :                     }
   10897             : 
   10898             :                     // Set return air node number
   10899           0 :                     state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) = 0;
   10900           0 :                     std::string retNodeName = "";
   10901           0 :                     if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) {
   10902           0 :                         retNodeName = state.dataIPShortCut->cAlphaArgs(7);
   10903             :                     }
   10904           0 :                     std::string callDescription = cCurrentModuleObject + "=" + surf.Name;
   10905           0 :                     state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) =
   10906           0 :                         DataZoneEquipment::GetReturnAirNodeForZone(state, surf.Zone, retNodeName, callDescription);
   10907           0 :                     if (state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) == 0) {
   10908           0 :                         ShowSevereError(state,
   10909           0 :                                         format("{}{}=\"{}\", airflow window return air node not found for {} = {}",
   10910             :                                                RoutineName,
   10911             :                                                cCurrentModuleObject,
   10912           0 :                                                surf.Name,
   10913           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3),
   10914           0 :                                                state.dataIPShortCut->cAlphaArgs(3)));
   10915           0 :                         if (!state.dataIPShortCut->lAlphaFieldBlanks(7))
   10916           0 :                             ShowContinueError(state,
   10917           0 :                                               format("{}=\"{}\" did not find a matching return air node.",
   10918           0 :                                                      state.dataIPShortCut->cAlphaFieldNames(7),
   10919           0 :                                                      state.dataIPShortCut->cAlphaArgs(7)));
   10920           0 :                         ShowContinueError(state,
   10921             :                                           "..Airflow windows with Airflow Destination = ReturnAir must reference a controlled Zone (appear in a "
   10922             :                                           "ZoneHVAC:EquipmentConnections object) with at least one return air node.");
   10923           0 :                         ErrorsFound = true;
   10924             :                     }
   10925           0 :                 }
   10926           8 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(4), "AlwaysOnAtMaximumFlow")) {
   10927           8 :                     state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::MaxFlow;
   10928           0 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(4), "AlwaysOff")) {
   10929           0 :                     state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::AlwaysOff;
   10930           0 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(4), "ScheduledOnly")) {
   10931           0 :                     state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::Schedule;
   10932             :                 }
   10933           8 :                 state.dataSurface->SurfWinMaxAirflow(SurfNum) = state.dataIPShortCut->rNumericArgs(1);
   10934           8 :                 if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULEDONLY" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
   10935           0 :                     if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
   10936           0 :                         ErrorsFound = true;
   10937           0 :                         ShowSevereError(state,
   10938           0 :                                         format("{}=\"{}\", has {}=\"{}\"",
   10939             :                                                cCurrentModuleObject,
   10940           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
   10941           0 :                                                state.dataIPShortCut->cAlphaFieldNames(4),
   10942           0 :                                                state.dataIPShortCut->cAlphaArgs(4)));
   10943           0 :                         ShowContinueError(state,
   10944           0 :                                           format("..and {}=\"{}\", but no {} specified.",
   10945           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(5),
   10946           0 :                                                  state.dataIPShortCut->cAlphaArgs(5),
   10947           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(6)));
   10948             :                     } else {
   10949           0 :                         state.dataSurface->SurfWinAirflowHasSchedule(SurfNum) = true;
   10950           0 :                         state.dataSurface->SurfWinAirflowSchedulePtr(SurfNum) = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
   10951           0 :                         if (state.dataSurface->SurfWinAirflowSchedulePtr(SurfNum) == 0) {
   10952           0 :                             ErrorsFound = true;
   10953           0 :                             ShowSevereError(state,
   10954           0 :                                             format("{}=\"{}\", invalid {}=\"{}\"",
   10955             :                                                    cCurrentModuleObject,
   10956           0 :                                                    state.dataIPShortCut->cAlphaArgs(1),
   10957           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(6),
   10958           0 :                                                    state.dataIPShortCut->cAlphaArgs(6)));
   10959             :                         }
   10960             :                     }
   10961             :                 }
   10962             :                 // Warning if associated window is an interior window
   10963           8 :                 if (surf.ExtBoundCond != ExternalEnvironment && !ErrorsFound)
   10964           0 :                     ShowWarningError(state,
   10965           0 :                                      format("{}=\"{}\", is an Interior window; cannot be an airflow window.",
   10966             :                                             cCurrentModuleObject,
   10967           0 :                                             state.dataIPShortCut->cAlphaArgs(1)));
   10968           8 :                 if (!ErrorsFound) {
   10969             :                     // Require that gas in airflow gap has type = air
   10970           8 :                     MatGapFlow = state.dataConstruction->Construct(ConstrNum).LayerPoint(2);
   10971           8 :                     if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers == 3)
   10972           4 :                         MatGapFlow = state.dataConstruction->Construct(ConstrNum).LayerPoint(4);
   10973           8 :                     if (dynamic_cast<Material::MaterialGasMix const *>(state.dataMaterial->Material(MatGapFlow))->gases[0].type !=
   10974             :                         Material::GasType::Air) {
   10975           0 :                         ErrorsFound = true;
   10976           0 :                         ShowSevereError(state,
   10977           0 :                                         format("{}=\"{}\", Gas type not air in airflow gap of construction {}",
   10978             :                                                cCurrentModuleObject,
   10979           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
   10980           0 :                                                state.dataConstruction->Construct(ConstrNum).Name));
   10981             :                     }
   10982             :                     // Require that gas be air in airflow gaps on either side of a between glass shade/blind
   10983           8 :                     if (surf.HasShadeControl) {
   10984           4 :                         for (std::size_t listIndex = 0; listIndex < surf.windowShadingControlList.size(); ++listIndex) {
   10985           4 :                             int WSCPtr = surf.windowShadingControlList[listIndex];
   10986           4 :                             if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
   10987           4 :                                 ConstrNumSh = surf.shadedConstructionList[listIndex];
   10988           4 :                                 if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers == 2) {
   10989           2 :                                     MatGapFlow1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2);
   10990           2 :                                     MatGapFlow2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(4);
   10991             :                                 } else {
   10992           2 :                                     MatGapFlow1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(4);
   10993           2 :                                     MatGapFlow2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(6);
   10994             :                                 }
   10995           4 :                                 if (dynamic_cast<Material::MaterialGasMix const *>(state.dataMaterial->Material(MatGapFlow1))->gases[0].type !=
   10996           8 :                                         Material::GasType::Air ||
   10997           4 :                                     dynamic_cast<Material::MaterialGasMix const *>(state.dataMaterial->Material(MatGapFlow2))->gases[0].type !=
   10998             :                                         Material::GasType::Air) {
   10999           0 :                                     ErrorsFound = true;
   11000           0 :                                     ShowSevereError(state,
   11001           0 :                                                     format("{}=\"{}\", gas type must be air on either side of the shade/blind",
   11002             :                                                            cCurrentModuleObject,
   11003           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
   11004             :                                 }
   11005           4 :                                 break; // only need the first window shading control since they should be the same
   11006             :                             }
   11007             :                         }
   11008             :                     }
   11009             :                 }
   11010             :             }
   11011             : 
   11012             :         } // End of loop over window airflow controls
   11013             :     }
   11014             : 
   11015         796 :     void GetFoundationData(EnergyPlusData &state, bool &ErrorsFound)
   11016             :     {
   11017             : 
   11018             :         int NumAlphas;
   11019             :         int NumProps;
   11020             :         int IOStat;
   11021         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   11022             : 
   11023             :         // Read Kiva Settings
   11024         796 :         cCurrentModuleObject = "Foundation:Kiva:Settings";
   11025         796 :         int TotKivaStgs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11026             : 
   11027         796 :         if (TotKivaStgs > 1) {
   11028           0 :             ErrorsFound = true;
   11029           0 :             ShowSevereError(state, format("Multiple {} objects found. Only one is allowed.", cCurrentModuleObject));
   11030             :         }
   11031             : 
   11032         796 :         if (TotKivaStgs == 1) {
   11033          10 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   11034             :                                                                      cCurrentModuleObject,
   11035             :                                                                      1,
   11036           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
   11037             :                                                                      NumAlphas,
   11038           5 :                                                                      state.dataIPShortCut->rNumericArgs,
   11039             :                                                                      NumProps,
   11040             :                                                                      IOStat,
   11041           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   11042           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   11043           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   11044           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   11045             : 
   11046           5 :             int numF = 1;
   11047           5 :             int alpF = 1;
   11048             : 
   11049           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11050           5 :                 state.dataSurfaceGeometry->kivaManager.settings.soilK = state.dataIPShortCut->rNumericArgs(numF);
   11051             :             }
   11052           5 :             numF++;
   11053           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11054           5 :                 state.dataSurfaceGeometry->kivaManager.settings.soilRho = state.dataIPShortCut->rNumericArgs(numF);
   11055             :             }
   11056           5 :             numF++;
   11057           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11058           5 :                 state.dataSurfaceGeometry->kivaManager.settings.soilCp = state.dataIPShortCut->rNumericArgs(numF);
   11059             :             }
   11060           5 :             numF++;
   11061           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11062           5 :                 state.dataSurfaceGeometry->kivaManager.settings.groundSolarAbs = state.dataIPShortCut->rNumericArgs(numF);
   11063             :             }
   11064           5 :             numF++;
   11065           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11066           5 :                 state.dataSurfaceGeometry->kivaManager.settings.groundThermalAbs = state.dataIPShortCut->rNumericArgs(numF);
   11067             :             }
   11068           5 :             numF++;
   11069           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11070           5 :                 state.dataSurfaceGeometry->kivaManager.settings.groundRoughness = state.dataIPShortCut->rNumericArgs(numF);
   11071             :             }
   11072           5 :             numF++;
   11073           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11074           5 :                 state.dataSurfaceGeometry->kivaManager.settings.farFieldWidth = state.dataIPShortCut->rNumericArgs(numF);
   11075             :             }
   11076           5 :             numF++;
   11077             : 
   11078           5 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11079           5 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "ZeroFlux")) {
   11080           1 :                     state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::ZERO_FLUX;
   11081           4 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "GroundWater")) {
   11082           0 :                     state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::GROUNDWATER;
   11083           4 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "Autoselect")) {
   11084           4 :                     state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::AUTO;
   11085             :                 } else {
   11086           0 :                     ErrorsFound = true;
   11087           0 :                     ShowSevereError(state,
   11088           0 :                                     format("{}, {} is not a valid choice for {}",
   11089             :                                            cCurrentModuleObject,
   11090           0 :                                            state.dataIPShortCut->cAlphaArgs(alpF),
   11091           0 :                                            state.dataIPShortCut->cAlphaFieldNames(alpF)));
   11092             :                 }
   11093             :             }
   11094           5 :             alpF++;
   11095             : 
   11096           5 :             if (state.dataIPShortCut->lNumericFieldBlanks(numF) || state.dataIPShortCut->rNumericArgs(numF) == Constant::AutoCalculate) {
   11097             :                 // Autocalculate deep-ground depth (see KivaManager::defineDefaultFoundation() for actual calculation)
   11098           4 :                 state.dataSurfaceGeometry->kivaManager.settings.deepGroundDepth = 40.0;
   11099           4 :                 state.dataSurfaceGeometry->kivaManager.settings.autocalculateDeepGroundDepth = true;
   11100           4 :                 if (state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary != HeatBalanceKivaManager::KivaManager::Settings::AUTO) {
   11101           0 :                     ErrorsFound = true;
   11102           0 :                     ShowSevereError(state,
   11103           0 :                                     format("{}, {} should not be set to Autocalculate unless {} is set to Autoselect",
   11104             :                                            cCurrentModuleObject,
   11105           0 :                                            state.dataIPShortCut->cNumericFieldNames(numF),
   11106           0 :                                            state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11107             :                 }
   11108             :             } else {
   11109           1 :                 state.dataSurfaceGeometry->kivaManager.settings.deepGroundDepth = state.dataIPShortCut->rNumericArgs(numF);
   11110           1 :                 state.dataSurfaceGeometry->kivaManager.settings.autocalculateDeepGroundDepth = false;
   11111             :             }
   11112           5 :             numF++;
   11113           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11114           1 :                 state.dataSurfaceGeometry->kivaManager.settings.minCellDim = state.dataIPShortCut->rNumericArgs(numF);
   11115             :             }
   11116           5 :             numF++;
   11117           5 :             if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11118           1 :                 state.dataSurfaceGeometry->kivaManager.settings.maxGrowthCoeff = state.dataIPShortCut->rNumericArgs(numF);
   11119             :             }
   11120           5 :             numF++;
   11121             : 
   11122           5 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11123           1 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "Hourly")) {
   11124           1 :                     state.dataSurfaceGeometry->kivaManager.settings.timestepType = HeatBalanceKivaManager::KivaManager::Settings::HOURLY;
   11125           1 :                     state.dataSurfaceGeometry->kivaManager.timestep = 3600.; // seconds
   11126             :                 } else { // if (Util::SameString(state.dataIPShortCut->cAlphaArgs( alpF ), "Timestep"))
   11127           0 :                     state.dataSurfaceGeometry->kivaManager.settings.timestepType = HeatBalanceKivaManager::KivaManager::Settings::TIMESTEP;
   11128           0 :                     state.dataSurfaceGeometry->kivaManager.timestep = state.dataGlobal->MinutesPerTimeStep * 60.;
   11129             :                 }
   11130             :             }
   11131           5 :             alpF++;
   11132             :         }
   11133             : 
   11134             :         // Set default foundation (probably doesn't need to be called if there are no Kiva
   11135             :         // surfaces, but we don't know that yet). We call this here so that the default
   11136             :         // foundation is available for 1) the starting copy for user-defined Foundation:Kiva
   11137             :         // object default inputs, and 2) the actual default Foundation object if a
   11138             :         // user-defined Foundation:Kiva name is not referenced by a surface.
   11139         796 :         state.dataSurfaceGeometry->kivaManager.defineDefaultFoundation(state);
   11140             : 
   11141             :         // Read Foundation objects
   11142         796 :         cCurrentModuleObject = "Foundation:Kiva";
   11143         796 :         int TotKivaFnds = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11144             : 
   11145         796 :         if (TotKivaFnds > 0) {
   11146          14 :             for (int Loop = 1; Loop <= TotKivaFnds; ++Loop) {
   11147          14 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   11148             :                                                                          cCurrentModuleObject,
   11149             :                                                                          Loop,
   11150           7 :                                                                          state.dataIPShortCut->cAlphaArgs,
   11151             :                                                                          NumAlphas,
   11152           7 :                                                                          state.dataIPShortCut->rNumericArgs,
   11153             :                                                                          NumProps,
   11154             :                                                                          IOStat,
   11155           7 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
   11156           7 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
   11157           7 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
   11158           7 :                                                                          state.dataIPShortCut->cNumericFieldNames);
   11159             : 
   11160           7 :                 int numF = 1;
   11161           7 :                 int alpF = 1;
   11162             : 
   11163           7 :                 bool ErrorInName = false;
   11164             : 
   11165           7 :                 HeatBalanceKivaManager::FoundationKiva fndInput;
   11166             : 
   11167           7 :                 fndInput.name = state.dataIPShortCut->cAlphaArgs(alpF);
   11168           7 :                 alpF++;
   11169           7 :                 Util::IsNameEmpty(state, fndInput.name, cCurrentModuleObject, ErrorInName);
   11170           7 :                 if (ErrorInName) {
   11171           0 :                     ErrorsFound = true;
   11172           0 :                     continue;
   11173             :                 }
   11174             : 
   11175             :                 // Start with copy of default
   11176           7 :                 auto &fnd = fndInput.foundation;
   11177           7 :                 fnd = state.dataSurfaceGeometry->kivaManager.defaultFoundation.foundation;
   11178             : 
   11179             :                 // Indoor temperature
   11180           7 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11181           1 :                     fndInput.assumedIndoorTemperature = state.dataIPShortCut->rNumericArgs(numF);
   11182             :                 } else {
   11183           6 :                     fndInput.assumedIndoorTemperature = -9999;
   11184             :                 }
   11185           7 :                 numF++;
   11186             : 
   11187             :                 // Interior horizontal insulation
   11188           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11189           3 :                     int index = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11190           3 :                     if (index == 0) {
   11191           0 :                         ErrorsFound = true;
   11192           0 :                         ShowSevereError(state,
   11193           0 :                                         format("Did not find matching material for {}=\"{}\", {}, missing material = {}",
   11194             :                                                cCurrentModuleObject,
   11195             :                                                fndInput.name,
   11196           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11197           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11198           0 :                         continue;
   11199             :                     }
   11200           3 :                     auto *m = state.dataMaterial->Material(index);
   11201           3 :                     if (m->group != Material::Group::Regular || m->ROnly) {
   11202           0 :                         ErrorsFound = true;
   11203           0 :                         ShowSevereError(state,
   11204           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11205             :                                                cCurrentModuleObject,
   11206             :                                                fndInput.name,
   11207           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11208           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11209           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11210           0 :                         continue;
   11211             :                     }
   11212           3 :                     fndInput.intHIns.x = 0.0;
   11213           3 :                     fndInput.intHIns.material = Kiva::Material(m->Conductivity, m->Density, m->SpecHeat);
   11214           3 :                     fndInput.intHIns.depth = m->Thickness;
   11215             :                 }
   11216           7 :                 alpF++;
   11217             : 
   11218           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11219           3 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11220           3 :                         fndInput.intHIns.z = 0.0;
   11221             :                     } else {
   11222           0 :                         fndInput.intHIns.z = state.dataIPShortCut->rNumericArgs(numF);
   11223             :                     }
   11224           3 :                     numF++;
   11225           3 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11226           0 :                         ErrorsFound = true;
   11227           0 :                         ShowSevereError(state,
   11228           0 :                                         format("{}=\"{}\", {} defined, but no {}provided",
   11229             :                                                cCurrentModuleObject,
   11230             :                                                fndInput.name,
   11231           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF - 1),
   11232           0 :                                                state.dataIPShortCut->cNumericFieldNames(numF)));
   11233           0 :                         continue;
   11234             :                     } else {
   11235           3 :                         fndInput.intHIns.width = -state.dataIPShortCut->rNumericArgs(numF);
   11236             :                     }
   11237           3 :                     numF++;
   11238             :                 } else {
   11239           4 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11240           0 :                         ShowWarningError(
   11241             :                             state,
   11242           0 :                             format(
   11243           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11244           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11245             :                     }
   11246           4 :                     numF++;
   11247           4 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11248           0 :                         ShowWarningError(
   11249             :                             state,
   11250           0 :                             format(
   11251           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11252           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11253             :                     }
   11254           4 :                     numF++;
   11255             :                 }
   11256             : 
   11257             :                 // Interior vertical insulation
   11258           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11259           0 :                     int index = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11260           0 :                     if (index == 0) {
   11261           0 :                         ErrorsFound = true;
   11262           0 :                         ShowSevereError(state,
   11263           0 :                                         format("Did not find matching material for {}=\"{}\", {}, missing material = {}",
   11264             :                                                cCurrentModuleObject,
   11265             :                                                fndInput.name,
   11266           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11267           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11268           0 :                         continue;
   11269             :                     }
   11270           0 :                     auto *m = state.dataMaterial->Material(index);
   11271           0 :                     if (m->group != Material::Group::Regular || m->ROnly) {
   11272           0 :                         ErrorsFound = true;
   11273           0 :                         ShowSevereError(state,
   11274           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11275             :                                                cCurrentModuleObject,
   11276             :                                                fndInput.name,
   11277           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11278           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11279           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11280           0 :                         continue;
   11281             :                     }
   11282           0 :                     fndInput.intVIns.material = Kiva::Material(m->Conductivity, m->Density, m->SpecHeat);
   11283           0 :                     fndInput.intVIns.width = -m->Thickness;
   11284           0 :                     fndInput.intVIns.x = 0.0;
   11285           0 :                     fndInput.intVIns.z = 0.0;
   11286             :                 }
   11287           7 :                 alpF++;
   11288             : 
   11289           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11290           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11291           0 :                         ErrorsFound = true;
   11292           0 :                         ShowSevereError(state,
   11293           0 :                                         format("{}=\"{}\", {} defined, but no {}provided",
   11294             :                                                cCurrentModuleObject,
   11295             :                                                fndInput.name,
   11296           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF - 1),
   11297           0 :                                                state.dataIPShortCut->cNumericFieldNames(numF)));
   11298           0 :                         continue;
   11299             :                     } else {
   11300           0 :                         fndInput.intVIns.depth = state.dataIPShortCut->rNumericArgs(numF);
   11301             :                     }
   11302           0 :                     numF++;
   11303             :                 } else {
   11304           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11305           0 :                         ShowWarningError(
   11306             :                             state,
   11307           0 :                             format(
   11308           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11309           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11310             :                     }
   11311           7 :                     numF++;
   11312             :                 }
   11313             : 
   11314             :                 // Exterior horizontal insulation
   11315           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11316           0 :                     int index = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11317           0 :                     if (index == 0) {
   11318           0 :                         ErrorsFound = true;
   11319           0 :                         ShowSevereError(state,
   11320           0 :                                         format("Did not find matching material for {}=\"{}\", {}, missing material = {}",
   11321             :                                                cCurrentModuleObject,
   11322             :                                                fndInput.name,
   11323           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11324           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11325           0 :                         continue;
   11326             :                     }
   11327           0 :                     auto *m = state.dataMaterial->Material(index);
   11328           0 :                     if (m->group != Material::Group::Regular || m->ROnly) {
   11329           0 :                         ErrorsFound = true;
   11330           0 :                         ShowSevereError(state,
   11331           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11332             :                                                cCurrentModuleObject,
   11333             :                                                fndInput.name,
   11334           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11335           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11336           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11337           0 :                         continue;
   11338             :                     }
   11339           0 :                     fndInput.extHIns.x = 0.0;
   11340           0 :                     fndInput.extHIns.material = Kiva::Material(m->Conductivity, m->Density, m->SpecHeat);
   11341           0 :                     fndInput.extHIns.depth = m->Thickness;
   11342             :                 }
   11343           7 :                 alpF++;
   11344             : 
   11345           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11346           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11347           0 :                         fndInput.extHIns.z = 0.0;
   11348             :                     } else {
   11349           0 :                         fndInput.extHIns.z = state.dataIPShortCut->rNumericArgs(numF);
   11350             :                     }
   11351           0 :                     numF++;
   11352           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11353           0 :                         ErrorsFound = true;
   11354           0 :                         ShowSevereError(state,
   11355           0 :                                         format("{}=\"{}\", {} defined, but no {}provided",
   11356             :                                                cCurrentModuleObject,
   11357             :                                                fndInput.name,
   11358           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF - 1),
   11359           0 :                                                state.dataIPShortCut->cNumericFieldNames(numF)));
   11360           0 :                         continue;
   11361             :                     } else {
   11362           0 :                         fndInput.extHIns.width = state.dataIPShortCut->rNumericArgs(numF);
   11363             :                     }
   11364           0 :                     numF++;
   11365             :                 } else {
   11366           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11367           0 :                         ShowWarningError(
   11368             :                             state,
   11369           0 :                             format(
   11370           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11371           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11372             :                     }
   11373           7 :                     numF++;
   11374           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11375           0 :                         ShowWarningError(
   11376             :                             state,
   11377           0 :                             format(
   11378           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11379           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11380             :                     }
   11381           7 :                     numF++;
   11382             :                 }
   11383             : 
   11384             :                 // Exterior vertical insulation
   11385           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11386           4 :                     int index = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11387           4 :                     if (index == 0) {
   11388           0 :                         ErrorsFound = true;
   11389           0 :                         ShowSevereError(state,
   11390           0 :                                         format("Did not find matching material for {}=\"{}\", {}, missing material = {}",
   11391             :                                                cCurrentModuleObject,
   11392             :                                                fndInput.name,
   11393           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11394           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11395           0 :                         continue;
   11396             :                     }
   11397           4 :                     auto *m = state.dataMaterial->Material(index);
   11398           4 :                     if (m->group != Material::Group::Regular || m->ROnly) {
   11399           0 :                         ErrorsFound = true;
   11400           0 :                         ShowSevereError(state,
   11401           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11402             :                                                cCurrentModuleObject,
   11403             :                                                fndInput.name,
   11404           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11405           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11406           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11407           0 :                         continue;
   11408             :                     }
   11409           4 :                     fndInput.extVIns.material = Kiva::Material(m->Conductivity, m->Density, m->SpecHeat);
   11410           4 :                     fndInput.extVIns.width = m->Thickness;
   11411           4 :                     fndInput.extVIns.x = 0.0;
   11412           4 :                     fndInput.extVIns.z = 0.0;
   11413             :                 }
   11414           7 :                 alpF++;
   11415             : 
   11416           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11417           4 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11418           0 :                         ErrorsFound = true;
   11419           0 :                         ShowSevereError(state,
   11420           0 :                                         format("{}=\"{}\", {} defined, but no {}provided",
   11421             :                                                cCurrentModuleObject,
   11422             :                                                fndInput.name,
   11423           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF - 1),
   11424           0 :                                                state.dataIPShortCut->cNumericFieldNames(numF)));
   11425           0 :                         continue;
   11426             :                     } else {
   11427           4 :                         fndInput.extVIns.depth = state.dataIPShortCut->rNumericArgs(numF);
   11428             :                     }
   11429           4 :                     numF++;
   11430             :                 } else {
   11431           3 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11432           0 :                         ShowWarningError(
   11433             :                             state,
   11434           0 :                             format(
   11435           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11436           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11437             :                     }
   11438           3 :                     numF++;
   11439             :                 }
   11440             : 
   11441             :                 // Foundation wall
   11442           7 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11443           7 :                     fnd.wall.heightAboveGrade = state.dataIPShortCut->rNumericArgs(numF);
   11444             :                 }
   11445           7 :                 numF++;
   11446             : 
   11447           7 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11448           7 :                     fnd.wall.depthBelowSlab = state.dataIPShortCut->rNumericArgs(numF);
   11449             :                 }
   11450           7 :                 numF++;
   11451             : 
   11452           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11453           0 :                     fndInput.wallConstructionIndex = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataConstruction->Construct);
   11454           0 :                     if (fndInput.wallConstructionIndex == 0) {
   11455           0 :                         ErrorsFound = true;
   11456           0 :                         ShowSevereError(state,
   11457           0 :                                         format("Did not find matching construction for {}=\"{}\", {}, missing construction = {}",
   11458             :                                                cCurrentModuleObject,
   11459             :                                                fndInput.name,
   11460           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11461           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11462           0 :                         continue;
   11463             :                     }
   11464           0 :                     auto &c = state.dataConstruction->Construct(fndInput.wallConstructionIndex);
   11465           0 :                     c.IsUsed = true;
   11466           0 :                     if (c.TypeIsWindow) {
   11467           0 :                         ErrorsFound = true;
   11468           0 :                         ShowSevereError(state,
   11469           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11470             :                                                cCurrentModuleObject,
   11471             :                                                fndInput.name,
   11472           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11473           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11474           0 :                         ShowContinueError(state, "Cannot be a window construction");
   11475           0 :                         continue;
   11476             :                     }
   11477             :                 } else {
   11478           7 :                     fndInput.wallConstructionIndex = 0; // Use default wall construction
   11479             :                 }
   11480           7 :                 alpF++;
   11481             : 
   11482             :                 // Footing
   11483           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11484           0 :                     int index = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11485           0 :                     if (index == 0) {
   11486           0 :                         ErrorsFound = true;
   11487           0 :                         ShowSevereError(state,
   11488           0 :                                         format("Did not find matching material for {}=\"{}\", {}, missing material = {}",
   11489             :                                                cCurrentModuleObject,
   11490             :                                                fndInput.name,
   11491           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11492           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11493           0 :                         continue;
   11494             :                     }
   11495           0 :                     auto *m = state.dataMaterial->Material(index);
   11496           0 :                     if (m->group != Material::Group::Regular || m->ROnly) {
   11497           0 :                         ErrorsFound = true;
   11498           0 :                         ShowSevereError(state,
   11499           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11500             :                                                cCurrentModuleObject,
   11501             :                                                fndInput.name,
   11502           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF),
   11503           0 :                                                state.dataIPShortCut->cAlphaArgs(alpF)));
   11504           0 :                         ShowContinueError(state, "Must be of type \"Material\"");
   11505           0 :                         continue;
   11506             :                     }
   11507           0 :                     fndInput.footing.material = Kiva::Material(m->Conductivity, m->Density, m->SpecHeat);
   11508           0 :                     fndInput.footing.width = m->Thickness;
   11509           0 :                     fndInput.footing.x = 0.0;
   11510           0 :                     fndInput.footing.z = 0.0;
   11511             :                 }
   11512           7 :                 alpF++;
   11513             : 
   11514           7 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
   11515           0 :                     if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11516           0 :                         ErrorsFound = true;
   11517           0 :                         ShowSevereError(state,
   11518           0 :                                         format("{}=\"{}\", {} defined, but no {}provided",
   11519             :                                                cCurrentModuleObject,
   11520             :                                                fndInput.name,
   11521           0 :                                                state.dataIPShortCut->cAlphaFieldNames(alpF - 1),
   11522           0 :                                                state.dataIPShortCut->cNumericFieldNames(numF)));
   11523           0 :                         continue;
   11524             :                     } else {
   11525           0 :                         fndInput.footing.depth = state.dataIPShortCut->rNumericArgs(numF);
   11526             :                     }
   11527           0 :                     numF++;
   11528             :                 } else {
   11529           7 :                     if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11530           0 :                         ShowWarningError(
   11531             :                             state,
   11532           0 :                             format(
   11533           0 :                                 "{}=\"{}\", no {} defined", cCurrentModuleObject, fndInput.name, state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
   11534           0 :                         ShowContinueError(state, format("{} will not be used.", state.dataIPShortCut->cNumericFieldNames(numF)));
   11535             :                     }
   11536           7 :                     numF++;
   11537             :                 }
   11538             : 
   11539             :                 // General Blocks
   11540           7 :                 int numRemainingFields = NumAlphas - (alpF - 1) + NumProps - (numF - 1);
   11541           7 :                 if (numRemainingFields > 0) {
   11542           0 :                     int numBlocks = numRemainingFields / 4;
   11543           0 :                     if (mod(numRemainingFields, 4) != 0) {
   11544           0 :                         ShowWarningError(state,
   11545           0 :                                          format("{}=\"{}\", number of Block fields not even multiple of 4. Will read in {}",
   11546             :                                                 cCurrentModuleObject,
   11547             :                                                 fndInput.name,
   11548             :                                                 numBlocks));
   11549             :                     }
   11550           0 :                     for (int blockNum = 0; blockNum < numBlocks; blockNum++) {
   11551           0 :                         Kiva::InputBlock block;
   11552           0 :                         if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
   11553           0 :                             int index = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
   11554           0 :                             if (index == 0) {
   11555           0 :                                 ErrorsFound = true;
   11556           0 :                                 ShowSevereError(state,
   11557           0 :                                                 format("Did not find matching material for {}=\"{}\", {}, missing material = {}",
   11558             :                                                        cCurrentModuleObject,
   11559             :                                                        fndInput.name,
   11560           0 :                                                        state.dataIPShortCut->cAlphaFieldNames(alpF),
   11561           0 :                                                        state.dataIPShortCut->cAlphaArgs(alpF)));
   11562           0 :                                 continue;
   11563             :                             }
   11564           0 :                             auto *m = state.dataMaterial->Material(index);
   11565           0 :                             if (m->group != Material::Group::Regular || m->ROnly) {
   11566           0 :                                 ErrorsFound = true;
   11567           0 :                                 ShowSevereError(state,
   11568           0 :                                                 format("{}=\"{}\", invalid {}=\"{}",
   11569             :                                                        cCurrentModuleObject,
   11570             :                                                        fndInput.name,
   11571           0 :                                                        state.dataIPShortCut->cAlphaFieldNames(alpF),
   11572           0 :                                                        state.dataIPShortCut->cAlphaArgs(alpF)));
   11573           0 :                                 ShowContinueError(state, "Must be of type \"Material\"");
   11574           0 :                                 continue;
   11575             :                             }
   11576           0 :                             block.material = Kiva::Material(m->Conductivity, m->Density, m->SpecHeat);
   11577           0 :                             block.width = m->Thickness;
   11578             :                         } else {
   11579           0 :                             ErrorsFound = true;
   11580           0 :                             ShowSevereError(state,
   11581           0 :                                             format("{}=\"{}\", {} is required and not given.",
   11582             :                                                    cCurrentModuleObject,
   11583             :                                                    fndInput.name,
   11584           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(alpF)));
   11585           0 :                             continue;
   11586             :                         }
   11587           0 :                         alpF++;
   11588             : 
   11589           0 :                         if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11590           0 :                             block.depth = 0.0; // Temporary indicator to default to foundation depth
   11591             :                         } else {
   11592           0 :                             block.depth = state.dataIPShortCut->rNumericArgs(numF);
   11593             :                         }
   11594           0 :                         numF++;
   11595             : 
   11596           0 :                         if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11597           0 :                             ErrorsFound = true;
   11598           0 :                             ShowSevereError(state,
   11599           0 :                                             format("{}=\"{}\", {} defined, but no {}provided",
   11600             :                                                    cCurrentModuleObject,
   11601             :                                                    fndInput.name,
   11602           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(alpF - 1),
   11603           0 :                                                    state.dataIPShortCut->cNumericFieldNames(numF)));
   11604           0 :                             continue;
   11605             :                         } else {
   11606           0 :                             block.x = state.dataIPShortCut->rNumericArgs(numF);
   11607             :                         }
   11608           0 :                         numF++;
   11609             : 
   11610           0 :                         if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
   11611           0 :                             block.z = 0.0;
   11612             :                         } else {
   11613           0 :                             block.z = state.dataIPShortCut->rNumericArgs(numF);
   11614             :                         }
   11615           0 :                         numF++;
   11616             : 
   11617           0 :                         fnd.inputBlocks.push_back(block);
   11618             :                     }
   11619             :                 }
   11620             : 
   11621           7 :                 state.dataSurfaceGeometry->kivaManager.foundationInputs.push_back(fndInput);
   11622           7 :             }
   11623             :         }
   11624         796 :     }
   11625             : 
   11626         796 :     void GetOSCData(EnergyPlusData &state, bool &ErrorsFound)
   11627             :     {
   11628             : 
   11629             :         // SUBROUTINE INFORMATION:
   11630             :         //       AUTHOR         Linda Lawrie
   11631             :         //       DATE WRITTEN   May 2000
   11632             :         //       MODIFIED       Jul 2011, M.J. Witte and C.O. Pedersen, add new fields to OSC for last T, max and min
   11633             :         //       RE-ENGINEERED  na
   11634             : 
   11635             :         // PURPOSE OF THIS SUBROUTINE:
   11636             :         // This subroutine gets the OtherSideCoefficient data.
   11637             : 
   11638             :         // METHODOLOGY EMPLOYED:
   11639             :         // na
   11640             : 
   11641             :         // REFERENCES:
   11642             :         // Other Side Coefficient Definition
   11643             :         // OtherSideCoefficients,
   11644             :         //       \memo This object sets the other side conditions for a surface in a variety of ways.
   11645             :         //   A1, \field OtherSideCoeff Name
   11646             :         //       \required-field
   11647             :         //       \reference OSCNames
   11648             :         //       \reference OutFaceEnvNames
   11649             :         //   N1, \field Combined convective/radiative film coefficient
   11650             :         //       \required-field
   11651             :         //       \type real
   11652             :         //       \note if>0, N1 becomes exterior convective/radiative film coefficient and other fields
   11653             :         //       \note are used to calc outside air temp then exterior surface temp based on outside air
   11654             :         //       \note and specified coefficient
   11655             :         //       \note if<=0, then remaining fields calculate the outside surface temperature(?)
   11656             :         //       \note following fields are used in the equation:
   11657             :         //       \note SurfTemp=N7*TempZone + N4*OutsideDryBulb + N2*N3 + GroundTemp*N5 + WindSpeed*N6*OutsideDryBulb
   11658             :         //   N2, \field User selected Constant Temperature
   11659             :         //       \units C
   11660             :         //       \type real
   11661             :         //       \note This parameter will be overwritten by the values from the schedule(A2 below) if one is present
   11662             :         //   N3, \field Coefficient modifying the user selected constant temperature
   11663             :         //       \note This coefficient is used even with a schedule.  It should normally be 1.0 in that case
   11664             :         //   N4, \field Coefficient modifying the external dry bulb temperature
   11665             :         //       \type real
   11666             :         //   N5, \field Coefficient modifying the ground temperature
   11667             :         //       \type real
   11668             :         //   N6, \field Coefficient modifying the wind speed term (s/m)
   11669             :         //       \type real
   11670             :         //   N7, \field Coefficient modifying the zone air temperature part of the equation
   11671             :         //       \type real
   11672             :         //   A2, \field ScheduleName for constant temperature
   11673             :         //       \note Name of Schedule for values of "const" temperature.
   11674             :         //       \note Schedule values replace N2 - User selected constant temperature.
   11675             :         //       \type object-list
   11676             :         //       \object-list ScheduleNames
   11677             :         //   A3, \field Sinusoidal Variation of Constant Temperature Coefficient
   11678             :         //       \note Optionally used to vary Constant Temperature Coefficient with unitary sine wave
   11679             :         //       \type choice
   11680             :         //       \key Yes
   11681             :         //       \key No
   11682             :         //       \default No
   11683             :         //   N8; \field Period of Sinusoidal Variation
   11684             :         //       \note Use with sinusoidal variation to define the time period
   11685             :         //       \type real
   11686             :         //       \units hr
   11687             :         //       \default 24
   11688             :         //  N9, \field Previous Other Side Temperature Coefficient
   11689             :         //      \note This coeffient multiplies the other side temperature result from the
   11690             :         //      \note previous zone timestep
   11691             :         //      \type real
   11692             :         //      \default 0
   11693             :         // N10, \field Minimum Other Side Temperature
   11694             :         //      \type real
   11695             :         //      \units C
   11696             :         //      \default -100
   11697             :         // N11; \field Maximum Other Side Temperature
   11698             :         //      \type real
   11699             :         //      \units C
   11700             :         //      \default 200
   11701             : 
   11702             :         // Using/Aliasing
   11703             : 
   11704             :         using ScheduleManager::GetScheduleIndex;
   11705             : 
   11706             :         // Locals
   11707             :         // SUBROUTINE ARGUMENT DEFINITIONS:
   11708             : 
   11709             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11710             :         int NumAlphas;
   11711             :         int NumProps;
   11712             :         int Loop;
   11713             :         int IOStat;
   11714             :         int OSCNum;
   11715             :         bool ErrorInName;
   11716             :         bool IsBlank;
   11717         796 :         std::string cOSCLimitsString;
   11718         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   11719             : 
   11720         796 :         cCurrentModuleObject = "SurfaceProperty:OtherSideCoefficients";
   11721         796 :         state.dataSurface->TotOSC = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11722         796 :         state.dataSurface->OSC.allocate(state.dataSurface->TotOSC);
   11723             : 
   11724         796 :         OSCNum = 0;
   11725         817 :         for (Loop = 1; Loop <= state.dataSurface->TotOSC; ++Loop) {
   11726          42 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   11727             :                                                                      cCurrentModuleObject,
   11728             :                                                                      Loop,
   11729          21 :                                                                      state.dataIPShortCut->cAlphaArgs,
   11730             :                                                                      NumAlphas,
   11731          21 :                                                                      state.dataIPShortCut->rNumericArgs,
   11732             :                                                                      NumProps,
   11733             :                                                                      IOStat,
   11734          21 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   11735          21 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   11736          21 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   11737          21 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   11738          21 :             ErrorInName = false;
   11739          21 :             IsBlank = false;
   11740          21 :             Util::VerifyName(
   11741          21 :                 state, state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->OSC, OSCNum, ErrorInName, IsBlank, cCurrentModuleObject + " Name");
   11742          21 :             if (ErrorInName) {
   11743           0 :                 ErrorsFound = true;
   11744           0 :                 continue;
   11745             :             }
   11746             : 
   11747          21 :             ++OSCNum;
   11748          21 :             state.dataSurface->OSC(OSCNum).Name = state.dataIPShortCut->cAlphaArgs(1);
   11749          21 :             state.dataSurface->OSC(OSCNum).SurfFilmCoef = state.dataIPShortCut->rNumericArgs(1);
   11750          21 :             state.dataSurface->OSC(OSCNum).ConstTemp = state.dataIPShortCut->rNumericArgs(2); //  This will be replaced if  schedule is used
   11751          21 :             state.dataSurface->OSC(OSCNum).ConstTempCoef =
   11752          21 :                 state.dataIPShortCut->rNumericArgs(3); //  This multiplier is used (even with schedule).  It should normally be 1.0
   11753          21 :             state.dataSurface->OSC(OSCNum).ExtDryBulbCoef = state.dataIPShortCut->rNumericArgs(4);
   11754          21 :             state.dataSurface->OSC(OSCNum).GroundTempCoef = state.dataIPShortCut->rNumericArgs(5);
   11755          21 :             state.dataSurface->OSC(OSCNum).WindSpeedCoef = state.dataIPShortCut->rNumericArgs(6);
   11756          21 :             state.dataSurface->OSC(OSCNum).ZoneAirTempCoef = state.dataIPShortCut->rNumericArgs(7);
   11757          21 :             state.dataSurface->OSC(OSCNum).SinusoidPeriod = state.dataIPShortCut->rNumericArgs(8);
   11758             : 
   11759          21 :             if ((!state.dataIPShortCut->lAlphaFieldBlanks(2)) && (NumAlphas != 1)) { //  Const temp will come from schedule specified below.
   11760          18 :                 state.dataSurface->OSC(OSCNum).ConstTempScheduleName = state.dataIPShortCut->cAlphaArgs(2);
   11761          18 :                 if (!state.dataSurface->OSC(OSCNum).ConstTempScheduleName.empty()) {
   11762          18 :                     state.dataSurface->OSC(OSCNum).ConstTempScheduleIndex =
   11763          18 :                         GetScheduleIndex(state, state.dataSurface->OSC(OSCNum).ConstTempScheduleName);
   11764          18 :                     if (state.dataSurface->OSC(OSCNum).ConstTempScheduleIndex == 0) {
   11765           0 :                         ShowSevereError(state,
   11766           0 :                                         format("{}=\"{}\", invalid {}=\"{}",
   11767             :                                                cCurrentModuleObject,
   11768           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
   11769           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
   11770           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
   11771           0 :                         ErrorsFound = true;
   11772             :                     }
   11773             :                 }
   11774             :             }
   11775             : 
   11776          21 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
   11777             : 
   11778          18 :                 if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), "No")) {
   11779          17 :                     state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef = false;
   11780           1 :                 } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), "Yes")) {
   11781           1 :                     state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef = true;
   11782             :                 } else {
   11783           0 :                     ShowSevereError(state,
   11784           0 :                                     format("{}=\"{}\", invalid {}=\"{}",
   11785             :                                            cCurrentModuleObject,
   11786           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
   11787           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
   11788           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
   11789           0 :                     ErrorsFound = true;
   11790             :                 }
   11791             :             }
   11792             : 
   11793          21 :             if (state.dataIPShortCut->rNumericArgs(1) > 0.0 && !any_ne(state.dataIPShortCut->rNumericArgs({3, 7}), 0.0) &&
   11794           0 :                 (!state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef)) {
   11795           0 :                 ShowSevereError(state,
   11796           0 :                                 format("{}=\"{}\" has zeros for all coefficients.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   11797           0 :                 ShowContinueError(state, "...The outdoor air temperature for surfaces using this OtherSideCoefficients object will always be 0C.");
   11798             :             }
   11799             : 
   11800          22 :             if (state.dataIPShortCut->rNumericArgs(1) <= 0.0 && !any_ne(state.dataIPShortCut->rNumericArgs({3, 7}), 0.0) &&
   11801           1 :                 (!state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef)) {
   11802           0 :                 ShowSevereError(state,
   11803           0 :                                 format("{}=\"{}\" has zeros for all coefficients.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
   11804           0 :                 ShowContinueError(state,
   11805             :                                   "...The outside surface temperature for surfaces using this OtherSideCoefficients object will always be 0C.");
   11806             :             }
   11807             : 
   11808          21 :             state.dataSurface->OSC(OSCNum).TPreviousCoef = state.dataIPShortCut->rNumericArgs(9);
   11809             : 
   11810          21 :             if (!state.dataIPShortCut->lNumericFieldBlanks(10)) {
   11811           1 :                 state.dataSurface->OSC(OSCNum).MinLimitPresent = true;
   11812           1 :                 state.dataSurface->OSC(OSCNum).MinTempLimit = state.dataIPShortCut->rNumericArgs(10);
   11813           1 :                 cOSCLimitsString = format("{:.3R}", state.dataIPShortCut->rNumericArgs(10));
   11814             :             } else {
   11815          20 :                 cOSCLimitsString = "N/A";
   11816             :             }
   11817          21 :             if (!state.dataIPShortCut->lNumericFieldBlanks(11)) {
   11818           1 :                 state.dataSurface->OSC(OSCNum).MaxLimitPresent = true;
   11819           1 :                 state.dataSurface->OSC(OSCNum).MaxTempLimit = state.dataIPShortCut->rNumericArgs(11);
   11820           1 :                 cOSCLimitsString += format(",{:.3R}", state.dataIPShortCut->rNumericArgs(10));
   11821             :             } else {
   11822          20 :                 cOSCLimitsString += ",N/A";
   11823             :             }
   11824             :         }
   11825             : 
   11826         817 :         for (Loop = 1; Loop <= state.dataSurface->TotOSC; ++Loop) {
   11827          21 :             if (Loop == 1) {
   11828             :                 static constexpr std::string_view OSCFormat1(
   11829             :                     "! <Other Side Coefficients>,Name,Combined convective/radiative film coefficient {W/m2-K},User selected "
   11830             :                     "Constant Temperature {C},Coefficient modifying the constant temperature term,Coefficient modifying the external "
   11831             :                     "dry bulb temperature term,Coefficient modifying the ground temperature term,Coefficient modifying the wind speed "
   11832             :                     "term {s/m},Coefficient modifying the zone air temperature term,Constant Temperature Schedule Name,Sinusoidal "
   11833             :                     "Variation,Period of Sinusoidal Variation,Previous Other Side Temperature Coefficient,Minimum Other Side "
   11834             :                     "Temperature {C},Maximum Other Side Temperature {C}");
   11835           9 :                 print(state.files.eio, "{}\n", OSCFormat1);
   11836             :             }
   11837          21 :             if (state.dataSurface->OSC(Loop).SurfFilmCoef > 0.0) {
   11838           1 :                 state.dataIPShortCut->cAlphaArgs(1) = format("{:.3R}", state.dataSurface->OSC(Loop).SurfFilmCoef);
   11839           2 :                 SetupOutputVariable(state,
   11840             :                                     "Surface Other Side Coefficients Exterior Air Drybulb Temperature",
   11841             :                                     Constant::Units::C,
   11842           1 :                                     state.dataSurface->OSC(Loop).OSCTempCalc,
   11843             :                                     OutputProcessor::TimeStepType::System,
   11844             :                                     OutputProcessor::StoreType::Average,
   11845           1 :                                     state.dataSurface->OSC(Loop).Name);
   11846             :             } else {
   11847          20 :                 state.dataIPShortCut->cAlphaArgs(1) = "N/A";
   11848             :             }
   11849          21 :             if (state.dataSurface->OSC(Loop).ConstTempScheduleIndex != 0) {
   11850          18 :                 state.dataIPShortCut->cAlphaArgs(2) = state.dataSurface->OSC(Loop).ConstTempScheduleName;
   11851          18 :                 constexpr std::string_view format = "Other Side Coefficients,{},{},{},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{},{},{:.3R},{:.3R},{}\n";
   11852          54 :                 print(state.files.eio,
   11853             :                       format,
   11854          18 :                       state.dataSurface->OSC(Loop).Name,
   11855          18 :                       state.dataIPShortCut->cAlphaArgs(1),
   11856             :                       "N/A",
   11857          18 :                       state.dataSurface->OSC(Loop).ConstTempCoef,
   11858          18 :                       state.dataSurface->OSC(Loop).ExtDryBulbCoef,
   11859          18 :                       state.dataSurface->OSC(Loop).GroundTempCoef,
   11860          18 :                       state.dataSurface->OSC(Loop).WindSpeedCoef,
   11861          18 :                       state.dataSurface->OSC(Loop).ZoneAirTempCoef,
   11862          18 :                       state.dataIPShortCut->cAlphaArgs(2),
   11863          18 :                       state.dataIPShortCut->cAlphaArgs(3),
   11864          18 :                       state.dataSurface->OSC(Loop).SinusoidPeriod,
   11865          18 :                       state.dataSurface->OSC(Loop).TPreviousCoef,
   11866             :                       cOSCLimitsString);
   11867             :             } else {
   11868           3 :                 state.dataIPShortCut->cAlphaArgs(2) = "N/A";
   11869           3 :                 constexpr std::string_view format =
   11870             :                     "Other Side Coefficients,{},{},{:.2R},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{},{},{:.3R},{:.3R},{}\n";
   11871           9 :                 print(state.files.eio,
   11872             :                       format,
   11873           3 :                       state.dataSurface->OSC(Loop).Name,
   11874           3 :                       state.dataIPShortCut->cAlphaArgs(1),
   11875           3 :                       state.dataSurface->OSC(Loop).ConstTemp,
   11876           3 :                       state.dataSurface->OSC(Loop).ConstTempCoef,
   11877           3 :                       state.dataSurface->OSC(Loop).ExtDryBulbCoef,
   11878           3 :                       state.dataSurface->OSC(Loop).GroundTempCoef,
   11879           3 :                       state.dataSurface->OSC(Loop).WindSpeedCoef,
   11880           3 :                       state.dataSurface->OSC(Loop).ZoneAirTempCoef,
   11881           3 :                       state.dataIPShortCut->cAlphaArgs(2),
   11882           3 :                       state.dataIPShortCut->cAlphaArgs(3),
   11883           3 :                       state.dataSurface->OSC(Loop).SinusoidPeriod,
   11884           3 :                       state.dataSurface->OSC(Loop).TPreviousCoef,
   11885             :                       cOSCLimitsString);
   11886             :             }
   11887             :         }
   11888         796 :     }
   11889             : 
   11890         796 :     void GetOSCMData(EnergyPlusData &state, bool &ErrorsFound)
   11891             :     {
   11892             : 
   11893             :         // SUBROUTINE INFORMATION:
   11894             :         //       AUTHOR         Brent Griffith
   11895             :         //       DATE WRITTEN   November 2004
   11896             :         //       MODIFIED       na
   11897             :         //       RE-ENGINEERED  na
   11898             : 
   11899             :         // PURPOSE OF THIS SUBROUTINE:
   11900             :         // This subroutine gets the OtherSideConditionsModel data.
   11901             : 
   11902             :         // METHODOLOGY EMPLOYED:
   11903             :         // na
   11904             : 
   11905             :         // REFERENCES:
   11906             :         // derived from GetOSCData subroutine by Linda Lawrie
   11907             : 
   11908             :         //  OtherSideConditionsModel,
   11909             :         //      \memo This object sets up modifying the other side conditions for a surface from other model results.
   11910             :         //  A1, \field OtherSideConditionsModel Name
   11911             :         //      \required-field
   11912             :         //      \reference OSCMNames
   11913             :         //      \reference OutFaceEnvNames
   11914             :         //  A2; \field Type of Model to determine Boundary Conditions
   11915             :         //      \type choice
   11916             :         //      \key Transpired Collector
   11917             :         //      \key Vented PV Cavity
   11918             :         //      \key Hybrid PV Transpired Collector
   11919             : 
   11920             :         // Using/Aliasing
   11921             : 
   11922             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11923             :         int NumAlphas;
   11924             :         int NumProps;
   11925             :         int Loop;
   11926             :         int IOStat;
   11927             :         int OSCMNum;
   11928             :         bool ErrorInName;
   11929             :         bool IsBlank;
   11930         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   11931         796 :         cCurrentModuleObject = "SurfaceProperty:OtherSideConditionsModel";
   11932         796 :         state.dataSurface->TotOSCM = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   11933         796 :         state.dataSurface->OSCM.allocate(state.dataSurface->TotOSCM);
   11934             :         // OSCM is already initialized in derived type defn.
   11935             : 
   11936         796 :         OSCMNum = 0;
   11937         821 :         for (Loop = 1; Loop <= state.dataSurface->TotOSCM; ++Loop) {
   11938          50 :             state.dataInputProcessing->inputProcessor->getObjectItem(
   11939          25 :                 state, cCurrentModuleObject, Loop, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumProps, IOStat);
   11940          25 :             ErrorInName = false;
   11941          25 :             IsBlank = false;
   11942          25 :             Util::VerifyName(
   11943          25 :                 state, state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->OSCM, OSCMNum, ErrorInName, IsBlank, cCurrentModuleObject + " Name");
   11944          25 :             if (ErrorInName) {
   11945           0 :                 ErrorsFound = true;
   11946           0 :                 continue;
   11947             :             }
   11948             : 
   11949          25 :             ++OSCMNum;
   11950          25 :             state.dataSurface->OSCM(OSCMNum).Name = state.dataIPShortCut->cAlphaArgs(1);
   11951             :             // Note no validation of the below at this time:
   11952          25 :             state.dataSurface->OSCM(OSCMNum).Class = state.dataIPShortCut->cAlphaArgs(2);
   11953             :             // setup output vars for modeled coefficients
   11954          50 :             SetupOutputVariable(state,
   11955             :                                 "Surface Other Side Conditions Modeled Convection Air Temperature",
   11956             :                                 Constant::Units::C,
   11957          25 :                                 state.dataSurface->OSCM(OSCMNum).TConv,
   11958             :                                 OutputProcessor::TimeStepType::System,
   11959             :                                 OutputProcessor::StoreType::Average,
   11960          25 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11961          50 :             SetupOutputVariable(state,
   11962             :                                 "Surface Other Side Conditions Modeled Convection Heat Transfer Coefficient",
   11963             :                                 Constant::Units::W_m2K,
   11964          25 :                                 state.dataSurface->OSCM(OSCMNum).HConv,
   11965             :                                 OutputProcessor::TimeStepType::System,
   11966             :                                 OutputProcessor::StoreType::Average,
   11967          25 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11968          50 :             SetupOutputVariable(state,
   11969             :                                 "Surface Other Side Conditions Modeled Radiation Temperature",
   11970             :                                 Constant::Units::C,
   11971          25 :                                 state.dataSurface->OSCM(OSCMNum).TRad,
   11972             :                                 OutputProcessor::TimeStepType::System,
   11973             :                                 OutputProcessor::StoreType::Average,
   11974          25 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11975          50 :             SetupOutputVariable(state,
   11976             :                                 "Surface Other Side Conditions Modeled Radiation Heat Transfer Coefficient",
   11977             :                                 Constant::Units::W_m2K,
   11978          25 :                                 state.dataSurface->OSCM(OSCMNum).HRad,
   11979             :                                 OutputProcessor::TimeStepType::System,
   11980             :                                 OutputProcessor::StoreType::Average,
   11981          25 :                                 state.dataSurface->OSCM(OSCMNum).Name);
   11982             : 
   11983          25 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
   11984           0 :                 SetupEMSActuator(state,
   11985             :                                  "Other Side Boundary Conditions",
   11986           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   11987             :                                  "Convection Bulk Air Temperature",
   11988             :                                  "[C]",
   11989           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnTConv,
   11990           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideTConvValue);
   11991           0 :                 SetupEMSActuator(state,
   11992             :                                  "Other Side Boundary Conditions",
   11993           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   11994             :                                  "Convection Heat Transfer Coefficient",
   11995             :                                  "[W/m2-K]",
   11996           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnHConv,
   11997           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideHConvValue);
   11998           0 :                 SetupEMSActuator(state,
   11999             :                                  "Other Side Boundary Conditions",
   12000           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   12001             :                                  "Radiation Effective Temperature",
   12002             :                                  "[C]",
   12003           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnTRad,
   12004           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideTRadValue);
   12005           0 :                 SetupEMSActuator(state,
   12006             :                                  "Other Side Boundary Conditions",
   12007           0 :                                  state.dataSurface->OSCM(OSCMNum).Name,
   12008             :                                  "Radiation Linear Heat Transfer Coefficient",
   12009             :                                  "[W/m2-K]",
   12010           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideOnHrad,
   12011           0 :                                  state.dataSurface->OSCM(OSCMNum).EMSOverrideHradValue);
   12012             :             }
   12013             :         }
   12014             : 
   12015         821 :         for (Loop = 1; Loop <= state.dataSurface->TotOSCM; ++Loop) {
   12016          25 :             if (Loop == 1) {
   12017             :                 static constexpr std::string_view OSCMFormat1("! <Other Side Conditions Model>,Name,Class\n");
   12018          12 :                 print(state.files.eio, OSCMFormat1);
   12019             :             }
   12020          25 :             print(state.files.eio, "Other Side Conditions Model,{},{}\n", state.dataSurface->OSCM(Loop).Name, state.dataSurface->OSCM(Loop).Class);
   12021             :         }
   12022         796 :     }
   12023             : 
   12024         796 :     void GetMovableInsulationData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
   12025             :     {
   12026             : 
   12027             :         // SUBROUTINE INFORMATION:
   12028             :         //       AUTHOR         Linda Lawrie
   12029             :         //       DATE WRITTEN   May 2000
   12030             :         //       MODIFIED       na
   12031             :         //       RE-ENGINEERED  na
   12032             : 
   12033             :         // PURPOSE OF THIS SUBROUTINE:
   12034             :         // This subroutine gets the movable insulation data that can be associated with
   12035             :         // a surface.
   12036             : 
   12037             :         // METHODOLOGY EMPLOYED:
   12038             :         // na
   12039             : 
   12040             :         // REFERENCES:
   12041             :         // Movable Insulation Definition
   12042             :         // SurfaceControl:MovableInsulation,
   12043             :         //       \memo Exterior or Interior Insulation on opaque surfaces
   12044             :         //   A1, \field Insulation Type
   12045             :         //       \required-field
   12046             :         //       \type choice
   12047             :         //       \key Outside
   12048             :         //       \key Inside
   12049             :         //   A2, \field Surface Name
   12050             :         //       \required-field
   12051             :         //       \type object-list
   12052             :         //       \object-list SurfaceNames
   12053             :         //   A3, \field Material Name
   12054             :         //       \required-field
   12055             :         //       \object-list MaterialName
   12056             :         //   A4; \field Schedule Name
   12057             :         //        \required-field
   12058             :         //        \type object-list
   12059             :         //        \object-list ScheduleNames
   12060             : 
   12061             :         // Using/Aliasing
   12062             : 
   12063             :         using ScheduleManager::GetScheduleIndex;
   12064             : 
   12065             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   12066             :         int NAlphas;
   12067             :         int NNums;
   12068             :         int IOStat;
   12069             :         int Loop;
   12070             :         int NMatInsul;
   12071             :         int SurfNum;
   12072             :         int MaterNum;
   12073             :         int SchNum;
   12074             : 
   12075             :         enum class InsulationType
   12076             :         {
   12077             :             Invalid = -1,
   12078             :             Outside,
   12079             :             Inside,
   12080             :             Num
   12081             :         };
   12082         796 :         constexpr std::array<std::string_view, static_cast<int>(InsulationType::Num)> insulationTypeNamesUC = {"OUTSIDE", "INSIDE"};
   12083             : 
   12084         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   12085         796 :         cCurrentModuleObject = "SurfaceControl:MovableInsulation";
   12086         796 :         NMatInsul = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   12087         801 :         for (Loop = 1; Loop <= NMatInsul; ++Loop) {
   12088          10 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
   12089             :                                                                      cCurrentModuleObject,
   12090             :                                                                      Loop,
   12091           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
   12092             :                                                                      NAlphas,
   12093           5 :                                                                      state.dataIPShortCut->rNumericArgs,
   12094             :                                                                      NNums,
   12095             :                                                                      IOStat,
   12096           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
   12097           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
   12098           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
   12099           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
   12100           5 :             SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
   12101           5 :             MaterNum = Util::FindItemInPtrList(state.dataIPShortCut->cAlphaArgs(3), state.dataMaterial->Material, state.dataMaterial->TotMaterials);
   12102           5 :             auto *thisMaterial = state.dataMaterial->Material(MaterNum);
   12103           5 :             SchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
   12104           5 :             InsulationType insulationType = static_cast<InsulationType>(getEnumValue(insulationTypeNamesUC, state.dataIPShortCut->cAlphaArgs(1)));
   12105           5 :             if (insulationType == InsulationType::Invalid) {
   12106           0 :                 ShowSevereError(state,
   12107           0 :                                 format("{}, {}=\"{}\", invalid data.",
   12108             :                                        cCurrentModuleObject,
   12109           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
   12110           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
   12111           0 :                 ShowContinueError(state,
   12112           0 :                                   format(" invalid {}=\"{}\", [should be Inside or Outside]",
   12113           0 :                                          state.dataIPShortCut->cAlphaFieldNames(1),
   12114           0 :                                          state.dataIPShortCut->cAlphaArgs(1)));
   12115           0 :                 ErrorsFound = true;
   12116             :             }
   12117           5 :             if (SurfNum == 0) {
   12118           0 :                 ShowSevereError(state,
   12119           0 :                                 format("{}, {}=\"{}\", invalid data.",
   12120             :                                        cCurrentModuleObject,
   12121           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
   12122           0 :                                        state.dataIPShortCut->cAlphaArgs(2)));
   12123           0 :                 ShowContinueError(state, format(" invalid (not found) {}", state.dataIPShortCut->cAlphaFieldNames(2)));
   12124           0 :                 ErrorsFound = true;
   12125             :             } else {
   12126           5 :                 if (MaterNum == 0) {
   12127           0 :                     ShowSevereError(state,
   12128           0 :                                     format("{}, {}=\"{}\", invalid data.",
   12129             :                                            cCurrentModuleObject,
   12130           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
   12131           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
   12132           0 :                     ShowContinueError(
   12133             :                         state,
   12134           0 :                         format(" invalid (not found) {}=\"{}\"", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
   12135           0 :                     ErrorsFound = true;
   12136             :                 } else {
   12137             : 
   12138             :                     Array1D_string const cMaterialGroupType({-1, 18},
   12139             :                                                             {"invalid",
   12140             :                                                              "Material/Material:NoMass",
   12141             :                                                              "Material:AirGap",
   12142             :                                                              "WindowMaterial:Shade",
   12143             :                                                              "WindowMaterial:Glazing*",
   12144             :                                                              "WindowMaterial:Gas",
   12145             :                                                              "WindowMaterial:Blind",
   12146             :                                                              "WindowMaterial:GasMixture",
   12147             :                                                              "WindowMaterial:Screen",
   12148             :                                                              "Material:RoofVegetation",
   12149             :                                                              "Material:InfraredTransparent",
   12150             :                                                              "WindowMaterial:SimpleGlazingSystem",
   12151             :                                                              "WindowMaterial:ComplexShade",
   12152             :                                                              "WindowMaterial:Gap",
   12153             :                                                              "WindowMaterial:Glazing:EquivalentLayer",
   12154             :                                                              "WindowMaterial:Shade:EquivalentLayer",
   12155             :                                                              "WindowMaterial:Drape:EquivalentLayer",
   12156             :                                                              "WindowMaterial:Blind:EquivalentLayer",
   12157             :                                                              "WindowMaterial:Screen:EquivalentLayer",
   12158           5 :                                                              "WindowMaterial:Gap:EquivalentLayer"});
   12159             : 
   12160           5 :                     Material::Group const MaterialLayerGroup = thisMaterial->group;
   12161           5 :                     if ((MaterialLayerGroup == Material::Group::WindowSimpleGlazing) ||
   12162           5 :                         (MaterialLayerGroup == Material::Group::ShadeEquivalentLayer) ||
   12163           5 :                         (MaterialLayerGroup == Material::Group::DrapeEquivalentLayer) ||
   12164           5 :                         (MaterialLayerGroup == Material::Group::BlindEquivalentLayer) ||
   12165           5 :                         (MaterialLayerGroup == Material::Group::ScreenEquivalentLayer) ||
   12166             :                         (MaterialLayerGroup == Material::Group::GapEquivalentLayer)) {
   12167           0 :                         ShowSevereError(state, format("Invalid movable insulation material for {}:", cCurrentModuleObject));
   12168           0 :                         ShowContinueError(
   12169             :                             state,
   12170           0 :                             format("...Movable insulation material type specified = {}", cMaterialGroupType(static_cast<int>(MaterialLayerGroup))));
   12171           0 :                         ShowContinueError(state, format("...Movable insulation material name specified = {}", state.dataIPShortCut->cAlphaArgs(3)));
   12172           0 :                         ErrorsFound = true;
   12173             :                     }
   12174           5 :                     if (SchNum == 0) {
   12175           0 :                         ShowSevereError(state,
   12176           0 :                                         format("{}, {}=\"{}\", invalid data.",
   12177             :                                                cCurrentModuleObject,
   12178           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
   12179           0 :                                                state.dataIPShortCut->cAlphaArgs(2)));
   12180           0 :                         ShowContinueError(
   12181             :                             state,
   12182           0 :                             format(" invalid (not found) {}=\"{}\"", state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4)));
   12183           0 :                         ErrorsFound = true;
   12184             :                     } else {
   12185             :                         {
   12186           5 :                             switch (insulationType) {
   12187           2 :                             case InsulationType::Outside:
   12188           2 :                                 if (state.dataSurface->SurfMaterialMovInsulExt(SurfNum) > 0) {
   12189           0 :                                     ShowSevereError(state,
   12190           0 :                                                     format("{}, {}=\"{}\", already assigned.",
   12191             :                                                            cCurrentModuleObject,
   12192           0 :                                                            state.dataIPShortCut->cAlphaFieldNames(2),
   12193           0 :                                                            state.dataIPShortCut->cAlphaArgs(2)));
   12194           0 :                                     ShowContinueError(
   12195             :                                         state,
   12196           0 :                                         format("\"Outside\", was already assigned Material=\"{}\".",
   12197           0 :                                                state.dataMaterial->Material(state.dataSurface->SurfMaterialMovInsulInt(SurfNum))->Name));
   12198           0 :                                     ShowContinueError(state, format("attempting to assign Material=\"{}\".", thisMaterial->Name));
   12199           0 :                                     ErrorsFound = true;
   12200             :                                 }
   12201           2 :                                 state.dataSurface->SurfMaterialMovInsulExt(SurfNum) = MaterNum;
   12202           2 :                                 state.dataSurface->SurfSchedMovInsulExt(SurfNum) = SchNum;
   12203           2 :                                 state.dataSurface->AnyMovableInsulation = true;
   12204           2 :                                 if (thisMaterial->Resistance <= 0.0) {
   12205           0 :                                     if (thisMaterial->Conductivity <= 0.0 || thisMaterial->Thickness <= 0.0) {
   12206           0 :                                         ShowSevereError(state,
   12207           0 :                                                         format("{}, {}=\"{}\", invalid material.",
   12208             :                                                                cCurrentModuleObject,
   12209           0 :                                                                state.dataIPShortCut->cAlphaFieldNames(2),
   12210           0 :                                                                state.dataIPShortCut->cAlphaArgs(2)));
   12211           0 :                                         ShowContinueError(state, "\"Outside\", invalid material for movable insulation.");
   12212           0 :                                         ShowContinueError(state,
   12213           0 :                                                           format("Material=\"{}\",Resistance=[{:.3R}], must be > 0 for use in Movable Insulation.",
   12214           0 :                                                                  thisMaterial->Name,
   12215           0 :                                                                  thisMaterial->Resistance));
   12216           0 :                                         ErrorsFound = true;
   12217           0 :                                     } else if (thisMaterial->Conductivity > 0.0) {
   12218           0 :                                         thisMaterial->Resistance = thisMaterial->Thickness / thisMaterial->Conductivity;
   12219             :                                     }
   12220             :                                 }
   12221           2 :                                 if (thisMaterial->Conductivity <= 0.0) {
   12222           1 :                                     if (thisMaterial->Resistance <= 0.0) {
   12223           0 :                                         ShowSevereError(state,
   12224           0 :                                                         format("{}, {}=\"{}\", invalid material.",
   12225             :                                                                cCurrentModuleObject,
   12226           0 :                                                                state.dataIPShortCut->cAlphaFieldNames(2),
   12227           0 :                                                                state.dataIPShortCut->cAlphaArgs(2)));
   12228           0 :                                         ShowContinueError(state, "\"Outside\", invalid material for movable insulation.");
   12229           0 :                                         ShowContinueError(state,
   12230           0 :                                                           format("Material=\"{}\",Conductivity=[{:.3R}], must be > 0 for use in Movable Insulation.",
   12231           0 :                                                                  thisMaterial->Name,
   12232           0 :                                                                  thisMaterial->Conductivity));
   12233           0 :                                         ErrorsFound = true;
   12234             :                                     }
   12235             :                                 }
   12236           2 :                                 break;
   12237           3 :                             case InsulationType::Inside:
   12238           3 :                                 if (state.dataSurface->SurfMaterialMovInsulInt(SurfNum) > 0) {
   12239           0 :                                     ShowSevereError(state,
   12240           0 :                                                     cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
   12241           0 :                                                         state.dataIPShortCut->cAlphaArgs(2) + "\", already assigned.");
   12242           0 :                                     ShowContinueError(state,
   12243           0 :                                                       "\"Inside\", was already assigned Material=\"" +
   12244           0 :                                                           state.dataMaterial->Material(state.dataSurface->SurfMaterialMovInsulInt(SurfNum))->Name +
   12245             :                                                           "\".");
   12246           0 :                                     ShowContinueError(state, "attempting to assign Material=\"" + thisMaterial->Name + "\".");
   12247           0 :                                     ErrorsFound = true;
   12248             :                                 }
   12249           3 :                                 state.dataSurface->SurfMaterialMovInsulInt(SurfNum) = MaterNum;
   12250           3 :                                 state.dataSurface->SurfSchedMovInsulInt(SurfNum) = SchNum;
   12251           3 :                                 state.dataSurface->AnyMovableInsulation = true;
   12252           3 :                                 if (thisMaterial->Resistance <= 0.0) {
   12253           0 :                                     if (thisMaterial->Conductivity <= 0.0 || thisMaterial->Thickness <= 0.0) {
   12254           0 :                                         ShowSevereError(state,
   12255           0 :                                                         format("{}, {}=\"{}\", invalid material.",
   12256             :                                                                cCurrentModuleObject,
   12257           0 :                                                                state.dataIPShortCut->cAlphaFieldNames(2),
   12258           0 :                                                                state.dataIPShortCut->cAlphaArgs(2)));
   12259           0 :                                         ShowContinueError(state, "\"Inside\", invalid material for movable insulation.");
   12260           0 :                                         ShowContinueError(state,
   12261           0 :                                                           format("Material=\"{}\",Resistance=[{:.3R}], must be > 0 for use in Movable Insulation.",
   12262           0 :                                                                  thisMaterial->Name,
   12263           0 :                                                                  thisMaterial->Resistance));
   12264           0 :                                         ErrorsFound = true;
   12265           0 :                                     } else if (thisMaterial->Conductivity > 0.0) {
   12266           0 :                                         thisMaterial->Resistance = thisMaterial->Thickness / thisMaterial->Conductivity;
   12267             :                                     }
   12268             :                                 }
   12269           3 :                                 break;
   12270           0 :                             default:
   12271           0 :                                 assert(false);
   12272             :                             }
   12273             :                         }
   12274           5 :                         if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
   12275           0 :                             ShowSevereError(state,
   12276           0 :                                             format("{}, {}=\"{}\"",
   12277             :                                                    cCurrentModuleObject,
   12278           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(2),
   12279           0 :                                                    state.dataIPShortCut->cAlphaArgs(2)));
   12280           0 :                             ShowContinueError(state, "invalid use on a Window. Use WindowShadingControl instead.");
   12281           0 :                             ErrorsFound = true;
   12282             :                         }
   12283             :                     }
   12284           5 :                 }
   12285             :             }
   12286             :         }
   12287         796 :     }
   12288             : 
   12289             :     // Calculates the volume (m3) of a zone using the surfaces as possible.
   12290         796 :     void CalculateZoneVolume(EnergyPlusData &state)
   12291             :     {
   12292             :         // SUBROUTINE INFORMATION:
   12293             :         //       AUTHOR         Legacy Code
   12294             :         //       DATE WRITTEN   1992-1994
   12295             :         //       MODIFIED       Sep 2007, Mar 2017
   12296             : 
   12297             :         // METHODOLOGY EMPLOYED:
   12298             :         // Uses surface area information for calculations.  Modified to use the
   12299             :         // user-entered ceiling height (x floor area, if applicable) instead of using
   12300             :         // the calculated volume when the user enters the ceiling height.
   12301             : 
   12302             :         // REFERENCES:
   12303             :         // Legacy Code (IBLAST)
   12304             : 
   12305         796 :         Vectors::Polyhedron ZoneStruct;
   12306         796 :         bool initmsg = true;
   12307         796 :         bool ShowZoneSurfaces = (state.dataInputProcessing->inputProcessor->getNumSectionsFound("SHOWZONESURFACES_DEBUG") > 0);
   12308         796 :         EPVector<int> surfacenotused;
   12309             : 
   12310             :         enum class ZoneVolumeCalcMethod
   12311             :         {
   12312             :             Invalid = -1,
   12313             :             Enclosed,
   12314             :             FloorAreaTimesHeight1,
   12315             :             FloorAreaTimesHeight2,
   12316             :             CeilingAreaTimesHeight,
   12317             :             OpWallAreaTimesDistance,
   12318             :             UserProvided,
   12319             :             Num
   12320             :         };
   12321             : 
   12322         796 :         int countNotFullyEnclosedZones = 0;
   12323        5852 :         for (auto &thisZone : state.dataHeatBal->Zone) {
   12324        5056 :             if (!thisZone.HasFloor) {
   12325           4 :                 ShowWarningError(state,
   12326           4 :                                  format("No floor exists in Zone=\"{}\", zone floor area is zero. All values for this zone that are entered per "
   12327             :                                         "floor area will be zero.",
   12328           2 :                                         thisZone.Name));
   12329             :             }
   12330             : 
   12331        5056 :             Real64 SumAreas = 0.0;
   12332        5056 :             Real64 CalcVolume = 0.0;
   12333             :             // Use AllSurfaceFirst which includes air boundaries
   12334        5056 :             int NFaces = thisZone.AllSurfaceLast - thisZone.AllSurfaceFirst + 1;
   12335        5056 :             int notused = 0;
   12336        5056 :             ZoneStruct.NumSurfaceFaces = NFaces;
   12337        5056 :             ZoneStruct.SurfaceFace.allocate(NFaces);
   12338        5056 :             int NActFaces = 0;
   12339        5056 :             surfacenotused.dimension(NFaces, 0);
   12340             : 
   12341       49464 :             for (int SurfNum = thisZone.AllSurfaceFirst; SurfNum <= thisZone.AllSurfaceLast; ++SurfNum) {
   12342       44408 :                 auto &thisSurface = state.dataSurface->Surface(SurfNum);
   12343             :                 // Only include Base Surfaces in Calc.
   12344             : 
   12345       44408 :                 if (thisSurface.Class != SurfaceClass::Wall && thisSurface.Class != SurfaceClass::Floor && thisSurface.Class != SurfaceClass::Roof) {
   12346        9096 :                     ++notused;
   12347        9096 :                     surfacenotused(notused) = SurfNum;
   12348        9096 :                     continue;
   12349             :                 }
   12350             : 
   12351       35312 :                 ++NActFaces;
   12352       35312 :                 auto &thisFace = ZoneStruct.SurfaceFace(NActFaces);
   12353       35312 :                 thisFace.FacePoints.allocate(thisSurface.Sides);
   12354       35312 :                 thisFace.NSides = thisSurface.Sides;
   12355       35312 :                 thisFace.SurfNum = SurfNum;
   12356       35312 :                 thisFace.FacePoints({1, thisSurface.Sides}) = thisSurface.Vertex({1, thisSurface.Sides});
   12357       35312 :                 Vectors::CreateNewellAreaVector(thisFace.FacePoints, thisFace.NSides, thisFace.NewellAreaVector);
   12358       35312 :                 SumAreas += Vectors::VecLength(thisFace.NewellAreaVector);
   12359             :             }
   12360        5056 :             ZoneStruct.NumSurfaceFaces = NActFaces;
   12361             : 
   12362        5056 :             bool isFloorHorizontal = false;
   12363        5056 :             bool isCeilingHorizontal = false;
   12364        5056 :             bool areWallsVertical = false;
   12365        5056 :             std::tie(isFloorHorizontal, isCeilingHorizontal, areWallsVertical) = areSurfaceHorizAndVert(state, ZoneStruct);
   12366        5056 :             Real64 oppositeWallArea = 0.0;
   12367        5056 :             Real64 distanceBetweenOppositeWalls = 0.0;
   12368             : 
   12369        5056 :             bool areWallsSameHeight = areWallHeightSame(state, ZoneStruct);
   12370             : 
   12371        5056 :             std::vector<EdgeOfSurf> listOfedgeNotUsedTwice;
   12372        5056 :             bool isZoneEnclosed = isEnclosedVolume(ZoneStruct, listOfedgeNotUsedTwice);
   12373             :             ZoneVolumeCalcMethod volCalcMethod;
   12374             : 
   12375        5056 :             Real64 floorAreaForVolume = (thisZone.FloorArea > 0.0) ? thisZone.FloorArea : thisZone.geometricFloorArea;
   12376        5056 :             Real64 ceilingAreaForVolume = (thisZone.CeilingArea > 0.0) ? thisZone.CeilingArea : thisZone.geometricCeilingArea;
   12377             : 
   12378        5056 :             if (isZoneEnclosed) {
   12379        5032 :                 CalcVolume = Vectors::CalcPolyhedronVolume(state, ZoneStruct);
   12380        5032 :                 volCalcMethod = ZoneVolumeCalcMethod::Enclosed;
   12381          24 :             } else if (floorAreaForVolume > 0.0 && thisZone.CeilingHeight > 0.0 && areFloorAndCeilingSame(state, ZoneStruct)) {
   12382          16 :                 CalcVolume = floorAreaForVolume * thisZone.CeilingHeight;
   12383          16 :                 volCalcMethod = ZoneVolumeCalcMethod::FloorAreaTimesHeight1;
   12384           8 :             } else if (isFloorHorizontal && areWallsVertical && areWallsSameHeight && floorAreaForVolume > 0.0 && thisZone.CeilingHeight > 0.0) {
   12385           2 :                 CalcVolume = floorAreaForVolume * thisZone.CeilingHeight;
   12386           2 :                 volCalcMethod = ZoneVolumeCalcMethod::FloorAreaTimesHeight2;
   12387           6 :             } else if (isCeilingHorizontal && areWallsVertical && areWallsSameHeight && ceilingAreaForVolume > 0.0 && thisZone.CeilingHeight > 0.0) {
   12388           0 :                 CalcVolume = ceilingAreaForVolume * thisZone.CeilingHeight;
   12389           0 :                 volCalcMethod = ZoneVolumeCalcMethod::CeilingAreaTimesHeight;
   12390           6 :             } else if (areOppositeWallsSame(state, ZoneStruct, oppositeWallArea, distanceBetweenOppositeWalls)) {
   12391           4 :                 CalcVolume = oppositeWallArea * distanceBetweenOppositeWalls;
   12392           4 :                 volCalcMethod = ZoneVolumeCalcMethod::OpWallAreaTimesDistance;
   12393           2 :             } else if (thisZone.Volume == Constant::AutoCalculate) { // no user entered zone volume
   12394           0 :                 ShowSevereError(state,
   12395           0 :                                 format("For zone: {} it is not possible to calculate the volume from the surrounding surfaces so either provide the "
   12396             :                                        "volume value or define all the surfaces to fully enclose the zone.",
   12397           0 :                                        thisZone.Name));
   12398           0 :                 CalcVolume = 0.;
   12399           0 :                 volCalcMethod = ZoneVolumeCalcMethod::Invalid;
   12400             :             } else {
   12401           2 :                 CalcVolume = 0.;
   12402           2 :                 volCalcMethod = ZoneVolumeCalcMethod::UserProvided;
   12403             :             }
   12404        5056 :             if (!isZoneEnclosed) {
   12405          24 :                 ++countNotFullyEnclosedZones;
   12406          24 :                 if (state.dataGlobal->DisplayExtraWarnings) { // report missing
   12407           0 :                     ShowWarningError(state,
   12408           0 :                                      format("CalculateZoneVolume: The Zone=\"{}\" is not fully enclosed. To be fully enclosed, each edge of a "
   12409             :                                             "surface must also be an edge on one other surface.",
   12410           0 :                                             thisZone.Name));
   12411           0 :                     switch (volCalcMethod) {
   12412           0 :                     case ZoneVolumeCalcMethod::FloorAreaTimesHeight1:
   12413           0 :                         ShowContinueError(state,
   12414             :                                           "  The zone volume was calculated using the floor area times ceiling height method where the floor and "
   12415             :                                           "ceiling are the same except for the z-coordinates.");
   12416           0 :                         break;
   12417           0 :                     case ZoneVolumeCalcMethod::FloorAreaTimesHeight2:
   12418           0 :                         ShowContinueError(state,
   12419             :                                           "  The zone volume was calculated using the floor area times ceiling height method where the floor is "
   12420             :                                           "horizontal, the walls are vertical, and the wall heights are all the same.");
   12421           0 :                         break;
   12422           0 :                     case ZoneVolumeCalcMethod::CeilingAreaTimesHeight:
   12423           0 :                         ShowContinueError(state,
   12424             :                                           "  The zone volume was calculated using the ceiling area times ceiling height method where the ceiling is "
   12425             :                                           "horizontal, the walls are vertical, and the wall heights are all the same.");
   12426           0 :                         break;
   12427           0 :                     case ZoneVolumeCalcMethod::OpWallAreaTimesDistance:
   12428           0 :                         ShowContinueError(state,
   12429             :                                           "  The zone volume was calculated using the opposite wall area times the distance between them method ");
   12430           0 :                         break;
   12431           0 :                     case ZoneVolumeCalcMethod::UserProvided:
   12432           0 :                         ShowContinueError(state, "  The zone volume was provided as an input to the ZONE object ");
   12433           0 :                         break;
   12434           0 :                     case ZoneVolumeCalcMethod::Invalid:
   12435           0 :                         ShowContinueError(state, "  The zone volume was not calculated and an error exists. ");
   12436           0 :                         break;
   12437           0 :                     case ZoneVolumeCalcMethod::Enclosed: // should not be called but completes enumeration
   12438           0 :                         ShowContinueError(state, "  The zone volume was calculated using multiple pyramids and was fully enclosed. ");
   12439           0 :                         break;
   12440           0 :                     default:
   12441           0 :                         assert(false);
   12442             :                     }
   12443           0 :                     for (auto &edge : listOfedgeNotUsedTwice) {
   12444           0 :                         if (edge.count < 2) {
   12445           0 :                             ShowContinueError(
   12446             :                                 state,
   12447           0 :                                 fmt::format("  The surface \"{}\" has an edge that was used only once: it is not an edge on another surface",
   12448           0 :                                             state.dataSurface->Surface(edge.surfNum).Name));
   12449             : 
   12450             :                         } else {
   12451           0 :                             ShowContinueError(
   12452             :                                 state,
   12453           0 :                                 fmt::format("  The surface \"{}\" has an edge that was used {} times: it is an edge on three or more surfaces: ",
   12454           0 :                                             state.dataSurface->Surface(edge.surfNum).Name,
   12455           0 :                                             edge.count));
   12456           0 :                             std::string surfaceNames = "    It was found on the following Surfaces: ";
   12457           0 :                             for (int surfNum : edge.otherSurfNums) {
   12458           0 :                                 surfaceNames += fmt::format("'{}' ", state.dataSurface->Surface(surfNum).Name);
   12459           0 :                             }
   12460           0 :                             ShowContinueError(state, surfaceNames);
   12461           0 :                         }
   12462           0 :                         ShowContinueError(state, format("    Vertex start {{ {:.4R}, {:.4R}, {:.4R}}}", edge.start.x, edge.start.y, edge.start.z));
   12463           0 :                         ShowContinueError(state, format("    Vertex end   {{ {:.4R}, {:.4R}, {:.4R}}}", edge.end.x, edge.end.y, edge.end.z));
   12464           0 :                     }
   12465             :                 }
   12466             :             }
   12467        5056 :             if (thisZone.Volume > 0.0) { // User entered zone volume, produce message if not near calculated
   12468        2342 :                 if (CalcVolume > 0.0) {
   12469        2340 :                     if (std::abs(CalcVolume - thisZone.Volume) / thisZone.Volume > 0.05) {
   12470           2 :                         ++state.dataSurfaceGeometry->ErrCount5;
   12471           2 :                         if (state.dataSurfaceGeometry->ErrCount5 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
   12472           1 :                             if (initmsg) {
   12473           1 :                                 ShowMessage(state,
   12474             :                                             "Note that the following warning(s) may/will occur if you have not enclosed your zone completely.");
   12475           1 :                                 initmsg = false;
   12476             :                             }
   12477           1 :                             ShowWarningError(state, "Entered Zone Volumes differ from calculated zone volume(s).");
   12478           1 :                             ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
   12479             :                         }
   12480           2 :                         if (state.dataGlobal->DisplayExtraWarnings) {
   12481           0 :                             if (initmsg) {
   12482           0 :                                 ShowMessage(state,
   12483             :                                             "Note that the following warning(s) may/will occur if you have not enclosed your zone completely.");
   12484           0 :                                 initmsg = false;
   12485             :                             }
   12486             :                             // Warn user of using specified Zone Volume
   12487           0 :                             ShowWarningError(
   12488             :                                 state,
   12489           0 :                                 format("Entered Volume entered for Zone=\"{}\" significantly different from calculated Volume", thisZone.Name));
   12490           0 :                             ShowContinueError(state,
   12491           0 :                                               format("Entered Zone Volume value={:.2R}, Calculated Zone Volume value={:.2R}, entered volume will be "
   12492             :                                                      "used in calculations.",
   12493           0 :                                                      thisZone.Volume,
   12494             :                                                      CalcVolume));
   12495             :                         }
   12496             :                     }
   12497             :                 }
   12498        2714 :             } else if (thisZone.ceilingHeightEntered) { // User did not enter zone volume, but entered ceiling height
   12499         129 :                 if (floorAreaForVolume > 0.0) {
   12500         129 :                     thisZone.Volume = floorAreaForVolume * thisZone.CeilingHeight;
   12501             :                 } else { // ceiling height entered but floor area zero
   12502           0 :                     thisZone.Volume = CalcVolume;
   12503             :                 }
   12504             :             } else { // Neither ceiling height nor volume entered
   12505        2585 :                 thisZone.Volume = CalcVolume;
   12506             :             }
   12507             : 
   12508        5056 :             if (thisZone.Volume <= 0.0) {
   12509           0 :                 ShowWarningError(state, format("Indicated Zone Volume <= 0.0 for Zone={}", thisZone.Name));
   12510           0 :                 ShowContinueError(state, format("The calculated Zone Volume was={:.2R}", thisZone.Volume));
   12511           0 :                 ShowContinueError(state, "The simulation will continue with the Zone Volume set to 10.0 m3. ");
   12512           0 :                 ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
   12513           0 :                 thisZone.Volume = 10.;
   12514             :             }
   12515             :             // For now - pro-rate space volumes by floor area, if not entered
   12516       10124 :             for (int spaceNum : thisZone.spaceIndexes) {
   12517        5068 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
   12518             :                 // don't touch if already user-specified
   12519        5068 :                 if (thisSpace.Volume > 0.0) continue;
   12520        5068 :                 if (thisZone.numSpaces == 1) {
   12521        5050 :                     thisSpace.Volume = thisZone.Volume;
   12522          18 :                 } else if (thisZone.geometricFloorArea > 0.0) {
   12523          18 :                     thisSpace.Volume = thisZone.Volume * thisSpace.FloorArea / thisZone.geometricFloorArea;
   12524             :                 }
   12525        5056 :             }
   12526        5056 :             Real64 totSpacesVolume = 0.0;
   12527       10124 :             for (int spaceNum : thisZone.spaceIndexes) {
   12528        5068 :                 totSpacesVolume += state.dataHeatBal->space(spaceNum).Volume;
   12529        5056 :             }
   12530        5056 :             if (totSpacesVolume > 0.0) {
   12531       10124 :                 for (int spaceNum : thisZone.spaceIndexes) {
   12532        5068 :                     state.dataHeatBal->space(spaceNum).fracZoneVolume = state.dataHeatBal->space(spaceNum).Volume / totSpacesVolume;
   12533        5056 :                 }
   12534             :             } // else leave fractions at zero
   12535             : 
   12536        5056 :             if (ShowZoneSurfaces) {
   12537           0 :                 if (state.dataSurfaceGeometry->ShowZoneSurfaceHeaders) {
   12538           0 :                     print(state.files.debug, "{}\n", "===================================");
   12539           0 :                     print(state.files.debug, "{}\n", "showing zone surfaces used and not used in volume calculation");
   12540           0 :                     print(state.files.debug, "{}\n", "for volume calculation, only floors, walls and roofs/ceilings are used");
   12541           0 :                     print(state.files.debug, "{}\n", "surface class, 1=wall, 2=floor, 3=roof/ceiling");
   12542           0 :                     print(state.files.debug, "{}\n", "unused surface class(es), 5=internal mass, 11=window, 12=glass door");
   12543           0 :                     print(state.files.debug, "{}\n", "                          13=door, 14=shading, 15=overhang, 16=fin");
   12544           0 :                     print(state.files.debug, "{}\n", "                          17=TDD Dome, 18=TDD Diffuser");
   12545           0 :                     state.dataSurfaceGeometry->ShowZoneSurfaceHeaders = false;
   12546             :                 }
   12547           0 :                 print(state.files.debug, "{}\n", "===================================");
   12548           0 :                 print(state.files.debug, "zone={} calc volume={}\n", thisZone.Name, CalcVolume);
   12549           0 :                 print(state.files.debug, " nsurfaces={} nactual={}\n", NFaces, NActFaces);
   12550             :             }
   12551       40368 :             for (int faceNum = 1; faceNum <= ZoneStruct.NumSurfaceFaces; ++faceNum) {
   12552       35312 :                 auto &thisFace = ZoneStruct.SurfaceFace(faceNum);
   12553       35312 :                 if (ShowZoneSurfaces) {
   12554           0 :                     if (faceNum <= NActFaces) {
   12555           0 :                         auto &thisSurface = state.dataSurface->Surface(thisFace.SurfNum);
   12556           0 :                         print(state.files.debug, "surface={} nsides={}\n", thisFace.SurfNum, thisFace.NSides);
   12557           0 :                         print(state.files.debug, "surface name={} class={}\n", thisSurface.Name, thisSurface.Class);
   12558           0 :                         print(state.files.debug, "area={}\n", thisSurface.GrossArea);
   12559           0 :                         for (int iside = 1; iside <= thisFace.NSides; ++iside) {
   12560           0 :                             auto const &FacePoint(thisFace.FacePoints(iside));
   12561           0 :                             print(state.files.debug, "{} {} {}\n", FacePoint.x, FacePoint.y, FacePoint.z);
   12562             :                         }
   12563             :                     }
   12564             :                 }
   12565       35312 :                 thisFace.FacePoints.deallocate();
   12566             :             }
   12567        5056 :             if (ShowZoneSurfaces) {
   12568           0 :                 for (int SurfNum = 1; SurfNum <= notused; ++SurfNum) {
   12569           0 :                     print(state.files.debug,
   12570             :                           "notused:surface={} name={} class={}\n",
   12571             :                           surfacenotused(SurfNum),
   12572           0 :                           state.dataSurface->Surface(surfacenotused(SurfNum)).Name,
   12573           0 :                           state.dataSurface->Surface(surfacenotused(SurfNum)).Class);
   12574             :                 }
   12575             :             }
   12576             : 
   12577        5056 :             ZoneStruct.SurfaceFace.deallocate();
   12578        5056 :             surfacenotused.deallocate();
   12579             : 
   12580        5852 :         } // zone loop
   12581         796 :         if (!state.dataGlobal->DisplayExtraWarnings) {
   12582         745 :             if (countNotFullyEnclosedZones == 1) {
   12583          16 :                 ShowWarningError(
   12584             :                     state, "CalculateZoneVolume: 1 zone is not fully enclosed. For more details use:  Output:Diagnostics,DisplayExtrawarnings; ");
   12585         729 :             } else if (countNotFullyEnclosedZones > 1) {
   12586           8 :                 ShowWarningError(state,
   12587           8 :                                  format("CalculateZoneVolume: {} zones are not fully enclosed. For more details use:  "
   12588             :                                         "Output:Diagnostics,DisplayExtrawarnings; ",
   12589             :                                         countNotFullyEnclosedZones));
   12590             :             }
   12591             :         }
   12592         796 :     }
   12593             : 
   12594             :     // test if the volume described by the polyhedron if full enclosed (would not leak)
   12595        5056 :     bool isEnclosedVolume(DataVectorTypes::Polyhedron const &zonePoly, std::vector<EdgeOfSurf> &edgeNot2)
   12596             :     {
   12597             :         // J. Glazer - March 2017
   12598             : 
   12599        5056 :         std::vector<Vector> uniqueVertices = makeListOfUniqueVertices(zonePoly);
   12600             : 
   12601        5056 :         std::vector<EdgeOfSurf> edgeNot2orig = edgesNotTwoForEnclosedVolumeTest(zonePoly, uniqueVertices);
   12602             :         // if all edges had two counts then it is fully enclosed
   12603        5056 :         if (edgeNot2orig.empty()) {
   12604        4058 :             edgeNot2 = edgeNot2orig;
   12605        4058 :             return true;
   12606             :         } 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
   12607             :                  // on the "other side" of the edge Go through all the points looking for the number that are colinear and see if that is
   12608             :                  // consistent with the number of edges found that didn't have a count of two
   12609             :             DataVectorTypes::Polyhedron updatedZonePoly = updateZonePolygonsForMissingColinearPoints(
   12610         998 :                 zonePoly, uniqueVertices); // this is done after initial test since it is computationally intensive.
   12611         998 :             std::vector<EdgeOfSurf> edgeNot2again = edgesNotTwoForEnclosedVolumeTest(updatedZonePoly, uniqueVertices);
   12612         998 :             if (edgeNot2again.empty()) {
   12613         974 :                 return true;
   12614             :             } else {
   12615          48 :                 edgeNot2 = edgesInBoth(edgeNot2orig,
   12616          24 :                                        edgeNot2again); // only return a list of those edges that appear in both the original edge and the
   12617             :                                                        // revised edges this eliminates added edges that will confuse users and edges that
   12618             :                                                        // were caught by the updateZonePoly routine
   12619          24 :                 return false;
   12620             :             }
   12621         998 :         }
   12622        5056 :     }
   12623             : 
   12624             :     // returns a vector of edges that are in both vectors
   12625          24 :     std::vector<EdgeOfSurf> edgesInBoth(std::vector<EdgeOfSurf> edges1, std::vector<EdgeOfSurf> edges2)
   12626             :     {
   12627             :         // J. Glazer - June 2017
   12628             :         // this is not optimized but the number of edges for a typical polyhedron is 12 and is probably rarely bigger than 20.
   12629             : 
   12630          24 :         std::vector<EdgeOfSurf> inBoth;
   12631         288 :         for (const auto &e1 : edges1) {
   12632        3229 :             for (const auto &e2 : edges2) {
   12633        3181 :                 if (edgesEqualOnSameSurface(e1, e2)) {
   12634         216 :                     inBoth.push_back(e1);
   12635         216 :                     break;
   12636             :                 }
   12637         264 :             }
   12638          24 :         }
   12639          24 :         return inBoth;
   12640           0 :     }
   12641             : 
   12642             :     // returns true if the edges match - including the surface number
   12643        3181 :     bool edgesEqualOnSameSurface(EdgeOfSurf a, EdgeOfSurf b)
   12644             :     {
   12645        3181 :         if (a.surfNum != b.surfNum) {
   12646        2681 :             return false;
   12647             :         }
   12648             : 
   12649             :         // vertex comparison (we compare indices, so absolute equal)
   12650         500 :         return ((a.start == b.start && a.end == b.end) || (a.start == b.end && a.end == b.start));
   12651             :     }
   12652             : 
   12653             :     // returns the number of times the edges of the polyhedron of the zone are not used twice by the sides
   12654        6054 :     std::vector<EdgeOfSurf> edgesNotTwoForEnclosedVolumeTest(DataVectorTypes::Polyhedron const &zonePoly, std::vector<Vector> const &uniqueVertices)
   12655             :     {
   12656             :         // J. Glazer - March 2017
   12657             : 
   12658             :         using DataVectorTypes::Vector;
   12659             : 
   12660             :         struct EdgeByPts
   12661             :         {
   12662             :             int start;
   12663             :             int end;
   12664             :             int count;
   12665             :             int firstSurfNum;
   12666             :             std::vector<int> otherSurfNums;
   12667       94930 :             EdgeByPts() : start(0), end(0), count(0), firstSurfNum(0)
   12668             :             {
   12669       94930 :             }
   12670             :         };
   12671        6054 :         std::vector<EdgeByPts> uniqueEdges;
   12672        6054 :         uniqueEdges.reserve(zonePoly.NumSurfaceFaces * 6);
   12673             : 
   12674             :         // construct list of unique edges
   12675        6054 :         Vector curVertex;
   12676             :         int curVertexIndex;
   12677       49958 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12678       43904 :             Vector prevVertex;
   12679             :             int prevVertexIndex;
   12680      224533 :             for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12681      180629 :                 if (jVertex == 1) {
   12682       43904 :                     prevVertex = zonePoly.SurfaceFace(iFace).FacePoints(zonePoly.SurfaceFace(iFace).NSides); // the last point
   12683       43904 :                     prevVertexIndex = findIndexOfVertex(prevVertex, uniqueVertices);
   12684             :                 } else {
   12685      136725 :                     prevVertex = curVertex;
   12686      136725 :                     prevVertexIndex = curVertexIndex;
   12687             :                 }
   12688      180629 :                 curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12689      180629 :                 curVertexIndex = findIndexOfVertex(curVertex, uniqueVertices); // uses isAlmostEqual3dPt
   12690      361258 :                 auto it = std::find_if(uniqueEdges.begin(), uniqueEdges.end(), [&curVertexIndex, &prevVertexIndex](const auto &edge) {
   12691     3327787 :                     return ((edge.start == curVertexIndex && edge.end == prevVertexIndex) ||
   12692     3327787 :                             (edge.start == prevVertexIndex && edge.end == curVertexIndex));
   12693      361258 :                 });
   12694      180629 :                 if (it == uniqueEdges.end()) {
   12695       94930 :                     EdgeByPts curEdge;
   12696       94930 :                     curEdge.start = prevVertexIndex;
   12697       94930 :                     curEdge.end = curVertexIndex;
   12698       94930 :                     curEdge.count = 1;
   12699       94930 :                     curEdge.firstSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12700       94930 :                     uniqueEdges.emplace_back(curEdge);
   12701       94930 :                 } else {
   12702       85699 :                     ++(it->count);
   12703       85699 :                     it->otherSurfNums.push_back(zonePoly.SurfaceFace(iFace).SurfNum);
   12704             :                 }
   12705      180629 :             }
   12706       43904 :         }
   12707             :         // All edges for an enclosed polyhedron should be shared by two (and only two) sides.
   12708             :         // So if the count is not two for all edges, the polyhedron is not enclosed
   12709        6054 :         std::vector<EdgeOfSurf> edgesNotTwoCount;
   12710      100984 :         for (const auto &anEdge : uniqueEdges) {
   12711       94930 :             if (anEdge.count != 2) {
   12712        9479 :                 EdgeOfSurf curEdgeOne;
   12713        9479 :                 curEdgeOne.surfNum = anEdge.firstSurfNum;
   12714        9479 :                 curEdgeOne.start = uniqueVertices[anEdge.start];
   12715        9479 :                 curEdgeOne.end = uniqueVertices[anEdge.end];
   12716        9479 :                 curEdgeOne.count = anEdge.count;
   12717        9479 :                 curEdgeOne.otherSurfNums = anEdge.otherSurfNums;
   12718        9479 :                 edgesNotTwoCount.push_back(curEdgeOne);
   12719        9479 :             }
   12720        6054 :         }
   12721       12108 :         return edgesNotTwoCount;
   12722        6054 :     }
   12723             : 
   12724             :     // create a list of unique vertices given the polyhedron describing the zone
   12725        5056 :     std::vector<Vector> makeListOfUniqueVertices(DataVectorTypes::Polyhedron const &zonePoly)
   12726             :     {
   12727             :         // J. Glazer - March 2017
   12728             : 
   12729             :         using DataVectorTypes::Vector;
   12730        5056 :         std::vector<Vector> uniqVertices;
   12731        5056 :         uniqVertices.reserve(zonePoly.NumSurfaceFaces * 6);
   12732             : 
   12733       40368 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12734      177447 :             for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12735      142135 :                 Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12736      142135 :                 if (uniqVertices.size() == 0) {
   12737        5056 :                     uniqVertices.emplace_back(curVertex);
   12738             :                 } else {
   12739      137079 :                     bool found = false;
   12740      850302 :                     for (const auto &unqV : uniqVertices) {
   12741      807496 :                         if (isAlmostEqual3dPt(curVertex, unqV)) {
   12742       94273 :                             found = true;
   12743       94273 :                             break;
   12744             :                         }
   12745      137079 :                     }
   12746      137079 :                     if (!found) {
   12747       42806 :                         uniqVertices.emplace_back(curVertex);
   12748             :                     }
   12749             :                 }
   12750      142135 :             }
   12751             :         }
   12752        5056 :         return uniqVertices;
   12753           0 :     }
   12754             : 
   12755             :     // updates the polyhedron used to describe a zone to include points on an edge that are between and collinear to points already describing
   12756             :     // the edge
   12757         998 :     DataVectorTypes::Polyhedron updateZonePolygonsForMissingColinearPoints(DataVectorTypes::Polyhedron const &zonePoly,
   12758             :                                                                            std::vector<Vector> const &uniqVertices)
   12759             :     {
   12760             :         // J. Glazer - March 2017
   12761             : 
   12762             :         using DataVectorTypes::Vector;
   12763             : 
   12764         998 :         DataVectorTypes::Polyhedron updZonePoly = zonePoly; // set the return value to the original polyhedron describing the zone
   12765             : 
   12766       11125 :         for (auto &updFace : updZonePoly.SurfaceFace) {
   12767       10127 :             bool insertedVertext = true;
   12768       24057 :             while (insertedVertext) {
   12769       13930 :                 insertedVertext = false;
   12770       13930 :                 auto &vertices = updFace.FacePoints;
   12771       62615 :                 for (auto it = vertices.begin(); it != vertices.end(); ++it) {
   12772             : 
   12773       52488 :                     auto itnext = std::next(it);
   12774       52488 :                     if (itnext == std::end(vertices)) {
   12775        9872 :                         itnext = std::begin(vertices);
   12776             :                     }
   12777             : 
   12778       52488 :                     auto curVertex = *it;      // (AUTO_OK_OBJ) can't tell if a copy is the intended behavior here
   12779       52488 :                     auto nextVertex = *itnext; // (AUTO_OK_OBJ)
   12780             : 
   12781             :                     // now go through all the vertices and see if they are colinear with start and end vertices
   12782      930754 :                     for (const auto &testVertex : uniqVertices) {
   12783      882069 :                         if (!isAlmostEqual3dPt(curVertex, testVertex) && !isAlmostEqual3dPt(nextVertex, testVertex)) {
   12784      779113 :                             if (isPointOnLineBetweenPoints(curVertex, nextVertex, testVertex)) {
   12785        3803 :                                 vertices.insert(itnext, testVertex);
   12786        3803 :                                 ++updFace.NSides;
   12787        3803 :                                 insertedVertext = true;
   12788        3803 :                                 break;
   12789             :                             }
   12790             :                         }
   12791       52488 :                     }
   12792             :                     // Break out of the loop on vertices of the surface too, and start again at the while
   12793       52488 :                     if (insertedVertext) {
   12794        3803 :                         break;
   12795             :                     }
   12796       56291 :                 }
   12797             :             }
   12798             :         }
   12799         998 :         return updZonePoly;
   12800           0 :     }
   12801             : 
   12802             :     // test if the ceiling and floor are the same except for their height difference by looking at the corners
   12803          22 :     bool areFloorAndCeilingSame(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
   12804             :     {
   12805             :         // J. Glazer - March 2017
   12806             : 
   12807             :         // check if the floor and ceiling are the same
   12808             :         // this is almost equivalent to saying, if you ignore the z-coordinate, are the vertices the same
   12809             :         // so if you could all the unique vertices of the floor and ceiling, ignoring the z-coordinate, they
   12810             :         // should always be even (they would be two but you might define multiple surfaces that meet in a corner)
   12811             : 
   12812             :         using DataVectorTypes::Vector;
   12813             :         using DataVectorTypes::Vector2dCount;
   12814             :         using DataVectorTypes::Vector_2d;
   12815             : 
   12816          22 :         std::vector<Vector2dCount> floorCeilingXY;
   12817          22 :         floorCeilingXY.reserve(zonePoly.NumSurfaceFaces * 6);
   12818             : 
   12819             :         // make list of x and y coordinates for all faces that are on the floor or ceiling
   12820         248 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12821         226 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12822         414 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Floor ||
   12823         188 :                 state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Roof) {
   12824         390 :                 for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12825         312 :                     Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12826         312 :                     Vector2dCount curXYc;
   12827         312 :                     curXYc.x = curVertex.x;
   12828         312 :                     curXYc.y = curVertex.y;
   12829         312 :                     curXYc.count = 1;
   12830         312 :                     bool found = false;
   12831        1153 :                     for (Vector2dCount &curFloorCeiling : floorCeilingXY) { // can't use just "auto" because updating floorCeilingXY
   12832        1014 :                         if (isAlmostEqual2dPt(curXYc, curFloorCeiling)) {   // count ignored in comparison
   12833         173 :                             ++curFloorCeiling.count;
   12834         173 :                             found = true;
   12835         173 :                             break;
   12836             :                         }
   12837         312 :                     }
   12838         312 :                     if (!found) {
   12839         139 :                         floorCeilingXY.emplace_back(curXYc);
   12840             :                     }
   12841         312 :                 }
   12842             :             }
   12843             :         }
   12844             :         // now make sure every point has been counted and even number of times (usually twice)
   12845             :         // if they are then the ceiling and floor are (almost certainly) the same x and y coordinates.
   12846          22 :         bool areFlrAndClgSame = true;
   12847          22 :         if (floorCeilingXY.size() > 0) {
   12848         115 :             for (auto const &curFloorCeiling : floorCeilingXY) {
   12849          99 :                 if (curFloorCeiling.count % 2 != 0) {
   12850           6 :                     areFlrAndClgSame = false;
   12851           6 :                     break;
   12852             :                 }
   12853          22 :             }
   12854             :         } else {
   12855           0 :             areFlrAndClgSame = false;
   12856             :         }
   12857          22 :         return areFlrAndClgSame;
   12858          22 :     }
   12859             : 
   12860             :     // test if the walls of a zone are all the same height using the polyhedron describing the zone geometry
   12861        5056 :     bool areWallHeightSame(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
   12862             :     {
   12863             :         // J. Glazer - March 2017
   12864             : 
   12865             :         // test if all the wall heights are the same (all walls have the same maximum z-coordinate
   12866             : 
   12867        5056 :         bool areWlHgtSame = true;
   12868        5056 :         Real64 wallHeightZ = -Constant::BigNumber;
   12869        5056 :         bool foundWallHeight = false;
   12870       39395 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12871       34413 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12872       34413 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
   12873       22102 :                 Real64 maxZ = -Constant::BigNumber;
   12874      110439 :                 for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
   12875       88337 :                     Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
   12876       88337 :                     if (maxZ < curVertex.z) {
   12877       22147 :                         maxZ = curVertex.z;
   12878             :                     }
   12879       88337 :                 }
   12880       22102 :                 if (foundWallHeight) {
   12881       17068 :                     if (std::abs(maxZ - wallHeightZ) > Constant::TwoCentimeters) {
   12882          74 :                         areWlHgtSame = false;
   12883          74 :                         break;
   12884             :                     }
   12885             :                 } else {
   12886        5034 :                     wallHeightZ = maxZ;
   12887        5034 :                     foundWallHeight = true;
   12888             :                 }
   12889             :             }
   12890             :         }
   12891        5056 :         return areWlHgtSame;
   12892             :     }
   12893             : 
   12894             :     // tests if the floor is horizontal, ceiling is horizontal, and walls are vertical and returns all three as a tuple of booleans
   12895        5056 :     std::tuple<bool, bool, bool> areSurfaceHorizAndVert(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
   12896             :     {
   12897             :         // J. Glazer - March 2017
   12898             : 
   12899             :         // check if floors and ceilings are horizontal and walls are vertical
   12900        5056 :         bool isFlrHoriz = true;
   12901        5056 :         bool isClgHoriz = true;
   12902        5056 :         bool areWlVert = true;
   12903       40368 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12904       35312 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12905       35312 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Floor) {
   12906        6890 :                 if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt - 180.) > 1.) { // with 1 degree angle
   12907           0 :                     isFlrHoriz = false;
   12908             :                 }
   12909       28422 :             } else if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Roof) { // includes ceilings
   12910        5801 :                 if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt) > 1.) {            // with 1 degree angle of
   12911         252 :                     isClgHoriz = false;
   12912             :                 }
   12913       22621 :             } else if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
   12914       22621 :                 if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt - 90) > 1.) { // with 1 degree angle
   12915           2 :                     areWlVert = false;
   12916             :                 }
   12917             :             }
   12918             :         }
   12919       10112 :         return std::make_tuple(isFlrHoriz, isClgHoriz, areWlVert);
   12920             :     }
   12921             : 
   12922             :     // tests whether a pair of walls in the zone are the same except offset from one another and facing the opposite direction and also
   12923             :     // returns the wall area and distance between
   12924           6 :     bool areOppositeWallsSame(EnergyPlusData &state,
   12925             :                               DataVectorTypes::Polyhedron const &zonePoly,
   12926             :                               Real64 &oppositeWallArea,            // return the area of the wall that has an opposite wall
   12927             :                               Real64 &distanceBetweenOppositeWalls // returns distance
   12928             :     )
   12929             :     {
   12930             :         // J. Glazer - March 2017
   12931             : 
   12932             :         // approach: if opposite surfaces have opposite azimuth and same area, then check the distance between the
   12933             :         // vertices( one counting backwards ) and if it is the same distance than assume that it is the same.
   12934             :         using DataVectorTypes::Vector;
   12935           6 :         bool foundOppEqual = false;
   12936          19 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12937          17 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12938          17 :             if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
   12939          17 :                 std::vector<int> facesAtAz = listOfFacesFacingAzimuth(state, zonePoly, state.dataSurface->Surface(curSurfNum).Azimuth);
   12940          17 :                 bool allFacesEquidistant = true;
   12941          17 :                 oppositeWallArea = 0.;
   12942          38 :                 for (int curFace : facesAtAz) {
   12943          34 :                     int possOppFace = findPossibleOppositeFace(state, zonePoly, curFace);
   12944          34 :                     if (possOppFace > 0) { // an opposite fact was found
   12945          22 :                         oppositeWallArea += state.dataSurface->Surface(zonePoly.SurfaceFace(curFace).SurfNum).Area;
   12946          22 :                         if (!areCornersEquidistant(zonePoly, curFace, possOppFace, distanceBetweenOppositeWalls)) {
   12947           1 :                             allFacesEquidistant = false;
   12948           1 :                             break;
   12949             :                         }
   12950             :                     } else {
   12951          12 :                         allFacesEquidistant = false;
   12952          12 :                         break;
   12953             :                     }
   12954          17 :                 }
   12955          17 :                 if (allFacesEquidistant) {
   12956           4 :                     foundOppEqual = true;
   12957           4 :                     break; // only need to find the first case where opposite walls are the same
   12958             :                 }
   12959          17 :             }
   12960             :         }
   12961           6 :         return foundOppEqual;
   12962             :     }
   12963             : 
   12964             :     // provides a list of indices of polyhedron faces that are facing a specific azimuth
   12965          17 :     std::vector<int> listOfFacesFacingAzimuth(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly, Real64 const azimuth)
   12966             :     {
   12967             :         // J. Glazer - March 2017
   12968             : 
   12969          17 :         std::vector<int> facingAzimuth;
   12970          17 :         facingAzimuth.reserve(zonePoly.NumSurfaceFaces);
   12971             : 
   12972         187 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12973         170 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12974         170 :             if (General::rotAzmDiffDeg(state.dataSurface->Surface(curSurfNum).Azimuth, azimuth) < 1.) {
   12975          45 :                 facingAzimuth.emplace_back(iFace);
   12976             :             }
   12977             :         }
   12978          17 :         return facingAzimuth;
   12979           0 :     }
   12980             : 
   12981             :     // returns the index of the face of a polyhedron that is probably opposite of the face index provided
   12982          34 :     int findPossibleOppositeFace(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly, int const faceIndex)
   12983             :     {
   12984             :         // J. Glazer - March 2017
   12985             : 
   12986          34 :         int selectedSurNum = zonePoly.SurfaceFace(faceIndex).SurfNum;
   12987          34 :         Real64 selectedAzimuth = state.dataSurface->Surface(selectedSurNum).Azimuth;
   12988          34 :         Real64 oppositeAzimuth = fmod(selectedAzimuth + 180., 360.);
   12989          34 :         Real64 selectedArea = state.dataSurface->Surface(selectedSurNum).Area;
   12990          34 :         int selectedNumCorners = zonePoly.SurfaceFace(faceIndex).NSides;
   12991          34 :         int found = -1;
   12992             : 
   12993         222 :         for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
   12994         210 :             int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
   12995         420 :             if ((zonePoly.SurfaceFace(iFace).NSides == selectedNumCorners) &&
   12996         420 :                 (std::abs(state.dataSurface->Surface(curSurfNum).Area - selectedArea) < 0.01) &&
   12997          78 :                 (std::abs(state.dataSurface->Surface(curSurfNum).Azimuth - oppositeAzimuth) < 1.)) {
   12998          22 :                 found = iFace;
   12999          22 :                 break;
   13000             :             }
   13001             :         }
   13002          34 :         return found;
   13003             :     }
   13004             : 
   13005             :     // tests if the corners of one face of the polyhedron are the same distance from corners of another face
   13006          22 :     bool areCornersEquidistant(DataVectorTypes::Polyhedron const &zonePoly, int const faceIndex, int const opFaceIndex, Real64 &distanceBetween)
   13007             :     {
   13008             :         // J. Glazer - March 2017
   13009             : 
   13010          22 :         bool allAreEquidistant = true;
   13011          22 :         Real64 firstDistance = -99.;
   13012          22 :         if (zonePoly.SurfaceFace(faceIndex).NSides == zonePoly.SurfaceFace(opFaceIndex).NSides) { // double check that the number of sides match
   13013         107 :             for (int iVertex = 1; iVertex <= zonePoly.SurfaceFace(faceIndex).NSides; ++iVertex) {
   13014          86 :                 int iVertexOpp = 1 + zonePoly.SurfaceFace(faceIndex).NSides - iVertex; // count backwards for opposite face
   13015             :                 Real64 curDistBetwCorners =
   13016          86 :                     distance(zonePoly.SurfaceFace(faceIndex).FacePoints(iVertex), zonePoly.SurfaceFace(opFaceIndex).FacePoints(iVertexOpp));
   13017          86 :                 if (iVertex == 1) {
   13018          22 :                     firstDistance = curDistBetwCorners;
   13019             :                 } else {
   13020          64 :                     if (std::abs(curDistBetwCorners - firstDistance) > Constant::OneCentimeter) {
   13021           1 :                         allAreEquidistant = false;
   13022           1 :                         break;
   13023             :                     }
   13024             :                 }
   13025             :             }
   13026             :         } else {
   13027           0 :             allAreEquidistant = false;
   13028             :         }
   13029          22 :         if (allAreEquidistant) distanceBetween = firstDistance;
   13030          22 :         return allAreEquidistant;
   13031             :     }
   13032             : 
   13033             :     // test if two points in space are in the same position based on a small tolerance
   13034    19285734 :     bool isAlmostEqual3dPt(DataVectorTypes::Vector v1, DataVectorTypes::Vector v2)
   13035             :     {
   13036             :         // J. Glazer - March 2017
   13037             : 
   13038    20119852 :         return ((std::abs(v1.x - v2.x) < Constant::OneCentimeter) && (std::abs(v1.y - v2.y) < Constant::OneCentimeter) &&
   13039    20119852 :                 (std::abs(v1.z - v2.z) < Constant::OneCentimeter));
   13040             :     }
   13041             : 
   13042             :     // test if two points on a plane are in the same position based on a small tolerance
   13043        1014 :     bool isAlmostEqual2dPt(DataVectorTypes::Vector_2d v1, DataVectorTypes::Vector_2d v2)
   13044             :     {
   13045             :         // J. Glazer - March 2017
   13046             : 
   13047        1014 :         return ((std::abs(v1.x - v2.x) < Constant::OneCentimeter) && (std::abs(v1.y - v2.y) < Constant::OneCentimeter));
   13048             :     }
   13049             : 
   13050             :     // test if two points on a plane are in the same position based on a small tolerance (based on Vector2dCount comparison)
   13051           0 :     bool isAlmostEqual2dPt(DataVectorTypes::Vector2dCount v1, DataVectorTypes::Vector2dCount v2)
   13052             :     {
   13053             :         // J. Glazer - March 2017
   13054             : 
   13055           0 :         return ((std::abs(v1.x - v2.x) < Constant::OneCentimeter) && (std::abs(v1.y - v2.y) < Constant::OneCentimeter));
   13056             :     }
   13057             : 
   13058             :     // returns the index of vertex in a list that is in the same position in space as the given vertex
   13059      224533 :     int findIndexOfVertex(DataVectorTypes::Vector vertexToFind, std::vector<DataVectorTypes::Vector> listOfVertices)
   13060             :     {
   13061             :         // J. Glazer - March 2017
   13062             : 
   13063     1454727 :         for (std::size_t i = 0; i < listOfVertices.size(); i++) {
   13064     1454727 :             if (isAlmostEqual3dPt(listOfVertices[i], vertexToFind)) {
   13065      224533 :                 return i;
   13066             :             }
   13067             :         }
   13068           0 :         return -1;
   13069             :     }
   13070             : 
   13071             :     // returns the distance between two points in space
   13072     1026756 :     Real64 distance(DataVectorTypes::Vector v1, DataVectorTypes::Vector v2)
   13073             :     {
   13074             :         // J. Glazer - March 2017
   13075             : 
   13076     1026756 :         return sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2) + pow(v1.z - v2.z, 2));
   13077             :     }
   13078             : 
   13079     6817715 :     Real64 distanceFromPointToLine(DataVectorTypes::Vector start, DataVectorTypes::Vector end, DataVectorTypes::Vector test)
   13080             :     {
   13081             :         // np.linalg.norm(np.cross(e-s,p-s)/np.linalg.norm(e-s))
   13082     6817715 :         DataVectorTypes::Vector t = end - start;
   13083     6817715 :         t.normalize(); // Unit vector of start to end
   13084             : 
   13085     6817715 :         DataVectorTypes::Vector other = test - start;
   13086             : 
   13087     6817715 :         DataVectorTypes::Vector projection = DataVectorTypes::cross(t, other); // normal unit vector, that's the distance component
   13088    13635430 :         return projection.length();
   13089     6817715 :     }
   13090             : 
   13091             :     // tests if a point in space lies on the line segment defined by two other points
   13092     6817715 :     bool isPointOnLineBetweenPoints(DataVectorTypes::Vector start, DataVectorTypes::Vector end, DataVectorTypes::Vector test)
   13093             :     {
   13094             :         // J. Glazer - March 2017
   13095             :         // 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
   13096             :         // floor to the roof, cf #7383 compute the shortest distance from the point to the line first to avoid false positive
   13097     6817715 :         if (distanceFromPointToLine(start, end, test) <
   13098             :             Constant::OneCentimeter) { // distanceFromPointToLine always positive, it's calculated as norml_L2
   13099      282940 :             return (std::abs((distance(start, end) - (distance(start, test) + distance(test, end)))) < Constant::OneCentimeter);
   13100             :         }
   13101     6534775 :         return false;
   13102             :     }
   13103             : 
   13104     1355977 :     bool EdgeOfSurf::operator==(const EdgeOfSurf &other) const
   13105             :     {
   13106     4058640 :         return ((isAlmostEqual3dPt(this->start, other.start) && isAlmostEqual3dPt(this->end, other.end)) ||
   13107     4058640 :                 (isAlmostEqual3dPt(this->start, other.end) && isAlmostEqual3dPt(this->end, other.start)));
   13108             :     }
   13109             : 
   13110           0 :     bool EdgeOfSurf::operator!=(const EdgeOfSurf &other) const
   13111             :     {
   13112           0 :         return !(*this == other);
   13113             :     }
   13114             : 
   13115     6117112 :     bool EdgeOfSurf::containsPoints(const Vector &vertex) const
   13116             :     {
   13117    18272826 :         return (!isAlmostEqual3dPt(this->start, vertex) && !isAlmostEqual3dPt(this->end, vertex) &&
   13118    18272826 :                 isPointOnLineBetweenPoints(this->start, this->end, vertex));
   13119             :     }
   13120             : 
   13121        7155 :     double EdgeOfSurf::length() const
   13122             :     {
   13123        7155 :         return distance(this->start, this->end);
   13124             :     }
   13125             : 
   13126       43646 :     void ProcessSurfaceVertices(EnergyPlusData &state, int const ThisSurf, bool &ErrorsFound)
   13127             :     {
   13128             :         // SUBROUTINE INFORMATION:
   13129             :         //       AUTHOR         Legacy Code (Walton)
   13130             :         //       DATE WRITTEN   1976
   13131             :         //       MODIFIED        FW, Mar 2002: Add triangular windows
   13132             :         //                       FW, May 2002: modify test for 4-sided but non-rectangular subsurfaces
   13133             :         //                       FW, Sep 2002: add shape for base surfaces (walls and detached shading surfaces)
   13134             : 
   13135             :         // PURPOSE OF THIS SUBROUTINE:
   13136             :         // This subroutine processes each surface into the vertex representation used
   13137             :         // by the shading procedures.
   13138             : 
   13139             :         // METHODOLOGY EMPLOYED:
   13140             :         // Detached Shading, Base Surfaces, Attached Shading surfaces are represented in the
   13141             :         // same manner as original.  Subsurfaces (windows, doors) are a "relative coordinate".
   13142             : 
   13143             :         using namespace Vectors;
   13144             : 
   13145             :         static constexpr std::string_view RoutineName("ProcessSurfaceVertices: ");
   13146             : 
   13147             :         Real64 X1;           // Intermediate Result
   13148             :         Real64 Y1;           // Intermediate Result
   13149             :         Real64 Z1;           // Intermediate Result
   13150             :         Real64 XLLC;         // X-coordinate of lower left corner
   13151             :         Real64 YLLC;         // Y-coordinate of lower left corner
   13152             :         Real64 ZLLC;         // Z-coordinate of lower left corner
   13153             :         int n;               // Vertex Number in Loop
   13154             :         int ThisBaseSurface; // Current base surface
   13155             :         Real64 Xp;
   13156             :         Real64 Yp;
   13157             :         Real64 Zp;
   13158             :         Real64 SurfWorldAz; // Surface Azimuth (facing)
   13159             :         Real64 SurfTilt;    // Surface Tilt
   13160       43646 :         SurfaceShape ThisShape(SurfaceShape::None);
   13161             :         bool BaseSurface; // True if a base surface or a detached shading surface
   13162             :         Real64 ThisSurfAz;
   13163             :         Real64 ThisSurfTilt;
   13164             :         Real64 ThisReveal;
   13165             :         Real64 ThisWidth;
   13166             :         Real64 ThisHeight;
   13167             :         int FrDivNum;        // Frame/divider number
   13168             :         Real64 FrWidth;      // Frame width for exterior windows (m)
   13169             :         Real64 FrArea;       // Frame area for exterior windows(m2)
   13170             :         Real64 DivWidth;     // Divider width for exterior windows (m)
   13171             :         Real64 DivArea;      // Divider area for exterior windows (m2)
   13172             :         Real64 DivFrac;      // Fraction of divider area without overlaps
   13173             :         bool ErrorInSurface; // false/true, depending on pass through routine
   13174             :         bool SError;         // Bool used for return value of calls to PlaneEquation
   13175             :         bool HeatTransSurf;
   13176             :         bool IsCoPlanar;
   13177             :         Real64 OutOfLine;
   13178             :         int LastVertexInError;
   13179             : 
   13180             :         // Object Data
   13181       43646 :         PlaneEq BasePlane;
   13182       43646 :         Vector TVect;
   13183       43646 :         Vector CoordinateTransVector;
   13184             : 
   13185       43646 :         if (state.dataSurface->Surface(ThisSurf).VerticesProcessed) {
   13186           0 :             return;
   13187             :         }
   13188             : 
   13189       43646 :         ErrorInSurface = false;
   13190             : 
   13191       43646 :         if (state.dataSurfaceGeometry->ProcessSurfaceVerticesOneTimeFlag) {
   13192         765 :             state.dataSurfaceGeometry->Xpsv.allocate(state.dataSurface->MaxVerticesPerSurface);
   13193         765 :             state.dataSurfaceGeometry->Ypsv.allocate(state.dataSurface->MaxVerticesPerSurface);
   13194         765 :             state.dataSurfaceGeometry->Zpsv.allocate(state.dataSurface->MaxVerticesPerSurface);
   13195         765 :             state.dataSurfaceGeometry->Xpsv = 0.0;
   13196         765 :             state.dataSurfaceGeometry->Ypsv = 0.0;
   13197         765 :             state.dataSurfaceGeometry->Zpsv = 0.0;
   13198         765 :             state.dataSurfaceGeometry->ProcessSurfaceVerticesOneTimeFlag = false;
   13199             :         }
   13200             : 
   13201             :         // Categorize this surface
   13202       43646 :         auto &surf = state.dataSurface->Surface(ThisSurf);
   13203       43646 :         BaseSurface = (surf.BaseSurf == 0 || surf.BaseSurf == ThisSurf);
   13204             : 
   13205       43646 :         ThisBaseSurface = surf.BaseSurf; // Dont know if this is still needed or not
   13206       43646 :         HeatTransSurf = surf.HeatTransSurf;
   13207             : 
   13208             :         // Kludge for daylighting shelves
   13209       43646 :         if (surf.IsShadowing) {
   13210        1636 :             ThisBaseSurface = ThisSurf;
   13211        1636 :             HeatTransSurf = true;
   13212             :         }
   13213             : 
   13214             :         // IF (Surface(ThisSurf)%Name(1:3) /= 'Mir') THEN
   13215       43646 :         if (!surf.MirroredSurf) {
   13216       42828 :             CalcCoPlanarNess(surf.Vertex, surf.Sides, IsCoPlanar, OutOfLine, LastVertexInError);
   13217       42828 :             if (!IsCoPlanar) {
   13218           0 :                 if (OutOfLine > 0.01) {
   13219           0 :                     ShowSevereError(state,
   13220           0 :                                     format("{}Suspected non-planar surface:\"{}\", Max \"out of line\"={:.5T} at Vertex # {}",
   13221             :                                            RoutineName,
   13222           0 :                                            surf.Name,
   13223             :                                            OutOfLine,
   13224             :                                            LastVertexInError));
   13225             :                 } else {
   13226           0 :                     ShowWarningError(state,
   13227           0 :                                      format("{}Possible non-planar surface:\"{}\", Max \"out of line\"={:.5T} at Vertex # {}",
   13228             :                                             RoutineName,
   13229           0 :                                             surf.Name,
   13230             :                                             OutOfLine,
   13231             :                                             LastVertexInError));
   13232             :                 }
   13233             :                 //       ErrorInSurface=.TRUE.
   13234             :             }
   13235             :         }
   13236             : 
   13237       43646 :         if (BaseSurface) {
   13238       36950 :             SurfWorldAz = surf.Azimuth;
   13239       36950 :             SurfTilt = surf.Tilt;
   13240      185593 :             for (n = 1; n <= surf.Sides; ++n) {
   13241      148643 :                 state.dataSurfaceGeometry->Xpsv(n) = surf.Vertex(n).x;
   13242      148643 :                 state.dataSurfaceGeometry->Ypsv(n) = surf.Vertex(n).y;
   13243      148643 :                 state.dataSurfaceGeometry->Zpsv(n) = surf.Vertex(n).z;
   13244             :             }
   13245       36950 :             TVect = surf.Vertex(3) - surf.Vertex(2);
   13246       36950 :             ThisWidth = VecLength(TVect);
   13247       36950 :             TVect = surf.Vertex(2) - surf.Vertex(1);
   13248       36950 :             ThisHeight = VecLength(TVect);
   13249       36950 :             surf.Width = ThisWidth;
   13250       36950 :             surf.Height = ThisHeight; // For a horizontal surface this is actually length!
   13251       36950 :             if (surf.Sides == 3) {
   13252         197 :                 surf.Shape = SurfaceShape::Triangle;
   13253       36753 :             } else if (surf.Sides == 4) {
   13254             :                 // Test for rectangularity
   13255       36556 :                 if (isRectangle(state, ThisSurf)) {
   13256       31314 :                     surf.Shape = SurfaceShape::Rectangle;
   13257             :                 } else {
   13258        5242 :                     surf.Shape = SurfaceShape::Quadrilateral;
   13259             :                 }
   13260             :             } else { // Surface( ThisSurf ).Sides > 4
   13261         197 :                 surf.Shape = SurfaceShape::Polygonal;
   13262         197 :                 if (std::abs(ThisHeight * ThisWidth - surf.GrossArea) > 0.001) {
   13263         197 :                     surf.Width = std::sqrt(surf.GrossArea);
   13264         197 :                     surf.Height = surf.Width;
   13265         197 :                     ThisWidth = surf.Width;
   13266         197 :                     ThisHeight = surf.Height;
   13267             :                 }
   13268             :             }
   13269             : 
   13270             :         } else { // It's a subsurface to previous basesurface in this set of calls
   13271             : 
   13272        6696 :             ThisSurfAz = surf.Azimuth;
   13273        6696 :             ThisSurfTilt = surf.Tilt;
   13274             : 
   13275             :             // Retrieve base surface info
   13276        6696 :             Real64 const baseSurfWorldAz = state.dataSurface->Surface(ThisBaseSurface).Azimuth;
   13277        6696 :             Real64 const baseSurfTilt = state.dataSurface->Surface(ThisBaseSurface).Tilt;
   13278        6696 :             Real64 const BaseCosAzimuth = std::cos(baseSurfWorldAz * Constant::DegToRadians);
   13279        6696 :             Real64 const BaseSinAzimuth = std::sin(baseSurfWorldAz * Constant::DegToRadians);
   13280        6696 :             Real64 const BaseCosTilt = std::cos(baseSurfTilt * Constant::DegToRadians);
   13281        6696 :             Real64 const BaseSinTilt = std::sin(baseSurfTilt * Constant::DegToRadians);
   13282        6696 :             Real64 const BaseXLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).x;
   13283        6696 :             Real64 const BaseYLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).y;
   13284        6696 :             Real64 const BaseZLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).z;
   13285             : 
   13286        6696 :             if (HeatTransSurf) {
   13287             : 
   13288        6696 :                 if (surf.Sides == 4) {
   13289        6694 :                     ThisShape = SurfaceShape::RectangularDoorWindow;
   13290           2 :                 } else if (surf.Sides == 3 && surf.Class == SurfaceClass::Window) {
   13291           2 :                     ThisShape = SurfaceShape::TriangularWindow;
   13292           0 :                 } else if (surf.Sides == 3 && surf.Class == SurfaceClass::Door) {
   13293           0 :                     ThisShape = SurfaceShape::TriangularDoor;
   13294             :                 } else {
   13295           0 :                     assert(false);
   13296             :                 }
   13297             : 
   13298             :             } else { //  this is a shadowing subsurface
   13299             : 
   13300           0 :                 if (std::abs(state.dataSurface->Surface(surf.BaseSurf).Tilt - ThisSurfTilt) <= 0.01) {
   13301             :                     // left or right fin
   13302           0 :                     if (ThisSurfAz < 0.0) ThisSurfAz += 360.0;
   13303           0 :                     if (ThisSurfAz > state.dataSurface->Surface(surf.BaseSurf).Azimuth) {
   13304           0 :                         ThisShape = SurfaceShape::RectangularLeftFin;
   13305             :                     } else {
   13306           0 :                         ThisShape = SurfaceShape::RectangularRightFin;
   13307             :                     }
   13308             :                 } else {
   13309           0 :                     ThisShape = SurfaceShape::RectangularOverhang;
   13310             :                 }
   13311             :             }
   13312             : 
   13313             :             // Setting relative coordinates for shadowing calculations for subsurfaces
   13314        6696 :             switch (ThisShape) {
   13315        6694 :             case SurfaceShape::RectangularDoorWindow: { // Rectangular heat transfer subsurface
   13316        6694 :                 PlaneEquation(state.dataSurface->Surface(surf.BaseSurf).Vertex, state.dataSurface->Surface(surf.BaseSurf).Sides, BasePlane, SError);
   13317        6694 :                 if (SError) {
   13318           0 :                     ShowSevereError(state, format("{}Degenerate surface (likely two vertices equal):\"{}\".", RoutineName, surf.Name));
   13319           0 :                     ErrorInSurface = true;
   13320             :                 }
   13321        6694 :                 ThisReveal = -Pt2Plane(surf.Vertex(2), BasePlane);
   13322        6694 :                 if (std::abs(ThisReveal) < 0.0002) ThisReveal = 0.0;
   13323        6694 :                 surf.Reveal = ThisReveal;
   13324        6694 :                 Xp = surf.Vertex(2).x - BaseXLLC;
   13325        6694 :                 Yp = surf.Vertex(2).y - BaseYLLC;
   13326        6694 :                 Zp = surf.Vertex(2).z - BaseZLLC;
   13327        6694 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13328        6694 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13329        6694 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13330        6694 :                 TVect = surf.Vertex(3) - surf.Vertex(2);
   13331        6694 :                 ThisWidth = VecLength(TVect);
   13332        6694 :                 TVect = surf.Vertex(2) - surf.Vertex(1);
   13333        6694 :                 ThisHeight = VecLength(TVect);
   13334        6694 :                 surf.Width = ThisWidth;
   13335        6694 :                 surf.Height = ThisHeight;
   13336             : 
   13337             :                 // Processing of 4-sided but non-rectangular Window, Door or GlassDoor, for use in calc of convective air flow.
   13338        6694 :                 if (!isRectangle(state, ThisSurf)) {
   13339             : 
   13340             :                     // Transform the surface into an equivalent rectangular surface with the same area and aspect ratio.
   13341           1 :                     MakeEquivalentRectangle(state, ThisSurf, ErrorsFound);
   13342             : 
   13343           1 :                     if (state.dataGlobal->DisplayExtraWarnings) {
   13344           0 :                         ShowWarningError(state, format("{}Suspected 4-sided but non-rectangular Window, Door or GlassDoor:", RoutineName));
   13345           0 :                         ShowContinueError(
   13346             :                             state,
   13347           0 :                             format("Surface={} is transformed into an equivalent rectangular surface with the same area and aspect ratio. ",
   13348           0 :                                    surf.Name));
   13349             :                     }
   13350             :                 }
   13351             : 
   13352        6694 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13353        6694 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13354        6694 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC + surf.Width;
   13355        6694 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC + surf.Width;
   13356        6694 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC + surf.Height;
   13357        6694 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC + surf.Height;
   13358        6694 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC;
   13359        6694 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC;
   13360        6694 :                 state.dataSurfaceGeometry->Zpsv(1) = ZLLC;
   13361        6694 :                 state.dataSurfaceGeometry->Zpsv(2) = ZLLC;
   13362        6694 :                 state.dataSurfaceGeometry->Zpsv(3) = ZLLC;
   13363        6694 :                 state.dataSurfaceGeometry->Zpsv(4) = ZLLC;
   13364             : 
   13365        6694 :                 if (surf.Class == SurfaceClass::Window && surf.ExtBoundCond == ExternalEnvironment && surf.FrameDivider > 0) {
   13366         381 :                     FrDivNum = surf.FrameDivider;
   13367             :                     // Set flag for calculating beam solar reflection from outside and/or inside window reveal
   13368           0 :                     if ((surf.Reveal > 0.0 && state.dataSurface->FrameDivider(FrDivNum).OutsideRevealSolAbs > 0.0) ||
   13369         381 :                         (state.dataSurface->FrameDivider(FrDivNum).InsideSillDepth > 0.0 &&
   13370         762 :                          state.dataSurface->FrameDivider(FrDivNum).InsideSillSolAbs > 0.0) ||
   13371         378 :                         (state.dataSurface->FrameDivider(FrDivNum).InsideReveal > 0.0 &&
   13372           0 :                          state.dataSurface->FrameDivider(FrDivNum).InsideRevealSolAbs > 0.0))
   13373           3 :                         state.dataHeatBal->CalcWindowRevealReflection = true;
   13374             : 
   13375             :                     // For exterior window with frame, subtract frame area from base surface
   13376             :                     // (only rectangular windows are allowed to have a frame and/or divider;
   13377             :                     // Surface(ThisSurf)%FrameDivider will be 0 for triangular windows)
   13378         381 :                     FrWidth = state.dataSurface->FrameDivider(FrDivNum).FrameWidth;
   13379         381 :                     if (FrWidth > 0.0) {
   13380         130 :                         FrArea = (surf.Height + 2.0 * FrWidth) * (surf.Width + 2.0 * FrWidth) - surf.Area / surf.Multiplier;
   13381         130 :                         state.dataSurface->SurfWinFrameArea(ThisSurf) = FrArea * surf.Multiplier;
   13382         130 :                         if ((state.dataSurface->Surface(surf.BaseSurf).Area - state.dataSurface->SurfWinFrameArea(ThisSurf)) <= 0.0) {
   13383           0 :                             ShowSevereError(state, format("{}Base Surface=\"{}\", ", RoutineName, state.dataSurface->Surface(surf.BaseSurf).Name));
   13384           0 :                             ShowContinueError(state,
   13385           0 :                                               format("Window Surface=\"{}\" area (with frame) is too large to fit on the surface.", surf.Name));
   13386           0 :                             ShowContinueError(state,
   13387           0 :                                               format("Base surface area (-windows and doors)=[{:.2T}] m2, frame area=[{:.2T}] m2.",
   13388           0 :                                                      state.dataSurface->Surface(surf.BaseSurf).Area,
   13389           0 :                                                      state.dataSurface->SurfWinFrameArea(ThisSurf)));
   13390           0 :                             ErrorInSurface = true;
   13391             :                         }
   13392         130 :                         state.dataSurface->Surface(surf.BaseSurf).Area -= state.dataSurface->SurfWinFrameArea(ThisSurf);
   13393             :                     }
   13394             :                     // If exterior window has divider, subtract divider area to get glazed area
   13395         381 :                     DivWidth = state.dataSurface->FrameDivider(surf.FrameDivider).DividerWidth;
   13396         381 :                     if (DivWidth > 0.0 && !ErrorInSurface) {
   13397          64 :                         DivArea = DivWidth * (state.dataSurface->FrameDivider(FrDivNum).HorDividers * surf.Width +
   13398          64 :                                               state.dataSurface->FrameDivider(FrDivNum).VertDividers * surf.Height -
   13399          64 :                                               state.dataSurface->FrameDivider(FrDivNum).HorDividers *
   13400          64 :                                                   state.dataSurface->FrameDivider(FrDivNum).VertDividers * DivWidth);
   13401          64 :                         state.dataSurface->SurfWinDividerArea(ThisSurf) = DivArea * surf.Multiplier;
   13402          64 :                         if ((surf.Area - state.dataSurface->SurfWinDividerArea(ThisSurf)) <= 0.0) {
   13403           0 :                             ShowSevereError(state, format("{}Divider area exceeds glazed opening for window {}", RoutineName, surf.Name));
   13404           0 :                             ShowContinueError(state,
   13405           0 :                                               format("Window surface area=[{:.2T}] m2, divider area=[{:.2T}] m2.",
   13406           0 :                                                      surf.Area,
   13407           0 :                                                      state.dataSurface->SurfWinDividerArea(ThisSurf)));
   13408           0 :                             ErrorInSurface = true;
   13409             :                         }
   13410          64 :                         surf.Area -= state.dataSurface->SurfWinDividerArea(ThisSurf); // Glazed area
   13411          64 :                         if (DivArea <= 0.0) {
   13412           0 :                             ShowWarningError(state, format("{}Calculated Divider Area <= 0.0 for Window={}", RoutineName, surf.Name));
   13413           0 :                             if (state.dataSurface->FrameDivider(FrDivNum).HorDividers == 0) {
   13414           0 :                                 ShowContinueError(state, "..Number of Horizontal Dividers = 0.");
   13415             :                             }
   13416           0 :                             if (state.dataSurface->FrameDivider(FrDivNum).VertDividers == 0) {
   13417           0 :                                 ShowContinueError(state, "..Number of Vertical Dividers = 0.");
   13418             :                             }
   13419             :                         } else {
   13420          64 :                             auto &surfWin = state.dataSurface->SurfaceWindow(ThisSurf);
   13421          64 :                             surfWin.glazedFrac = surf.Area / (surf.Area + state.dataSurface->SurfWinDividerArea(ThisSurf));
   13422             :                             // Correction factor for portion of divider subject to divider projection correction
   13423          64 :                             DivFrac = (1.0 - state.dataSurface->FrameDivider(FrDivNum).HorDividers *
   13424          64 :                                                  state.dataSurface->FrameDivider(FrDivNum).VertDividers * pow_2(DivWidth) / DivArea);
   13425          64 :                             state.dataSurface->SurfWinProjCorrDivOut(ThisSurf) =
   13426          64 :                                 DivFrac * state.dataSurface->FrameDivider(FrDivNum).DividerProjectionOut / DivWidth;
   13427          64 :                             state.dataSurface->SurfWinProjCorrDivIn(ThisSurf) =
   13428          64 :                                 DivFrac * state.dataSurface->FrameDivider(FrDivNum).DividerProjectionIn / DivWidth;
   13429             :                             // Correction factor for portion of frame subject to frame projection correction
   13430          64 :                             if (FrWidth > 0.0) {
   13431          64 :                                 state.dataSurface->SurfWinProjCorrFrOut(ThisSurf) =
   13432          64 :                                     (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionOut / FrWidth) *
   13433         128 :                                     (ThisHeight + ThisWidth -
   13434          64 :                                      (state.dataSurface->FrameDivider(FrDivNum).HorDividers +
   13435          64 :                                       state.dataSurface->FrameDivider(FrDivNum).VertDividers) *
   13436          64 :                                          DivWidth) /
   13437          64 :                                     (ThisHeight + ThisWidth + 2 * FrWidth);
   13438          64 :                                 state.dataSurface->SurfWinProjCorrFrIn(ThisSurf) =
   13439          64 :                                     (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionIn / FrWidth) *
   13440         128 :                                     (ThisHeight + ThisWidth -
   13441          64 :                                      (state.dataSurface->FrameDivider(FrDivNum).HorDividers +
   13442          64 :                                       state.dataSurface->FrameDivider(FrDivNum).VertDividers) *
   13443          64 :                                          DivWidth) /
   13444          64 :                                     (ThisHeight + ThisWidth + 2 * FrWidth);
   13445             :                             }
   13446             :                         }
   13447             :                     }
   13448             :                 }
   13449        6694 :             } break;
   13450           2 :             case SurfaceShape::TriangularWindow:
   13451             :             case SurfaceShape::TriangularDoor: {
   13452           2 :                 PlaneEquation(state.dataSurface->Surface(surf.BaseSurf).Vertex, state.dataSurface->Surface(surf.BaseSurf).Sides, BasePlane, SError);
   13453           2 :                 if (SError) {
   13454           0 :                     ShowSevereError(state, format("{}Degenerate surface (likely two vertices equal):\"{}\".", RoutineName, surf.Name));
   13455           0 :                     ErrorInSurface = true;
   13456             :                 }
   13457           2 :                 ThisReveal = -Pt2Plane(surf.Vertex(2), BasePlane);
   13458           2 :                 if (std::abs(ThisReveal) < 0.0002) ThisReveal = 0.0;
   13459           2 :                 surf.Reveal = ThisReveal;
   13460           2 :                 Xp = surf.Vertex(2).x - BaseXLLC;
   13461           2 :                 Yp = surf.Vertex(2).y - BaseYLLC;
   13462           2 :                 Zp = surf.Vertex(2).z - BaseZLLC;
   13463           2 :                 state.dataSurfaceGeometry->Xpsv(2) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13464           2 :                 state.dataSurfaceGeometry->Ypsv(2) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13465           2 :                 state.dataSurfaceGeometry->Zpsv(2) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13466           2 :                 TVect = surf.Vertex(3) - surf.Vertex(2);
   13467           2 :                 ThisWidth = VecLength(TVect);
   13468           2 :                 TVect = surf.Vertex(2) - surf.Vertex(1);
   13469           2 :                 ThisHeight = VecLength(TVect);
   13470           2 :                 surf.Width = ThisWidth;
   13471           2 :                 surf.Height = ThisHeight;
   13472             :                 // Effective height and width of a triangular window for use in calc of convective air flow
   13473             :                 // in gap between glass and shading device when shading device is present
   13474           2 :                 surf.Height = 4.0 * surf.Area / (3.0 * surf.Width);
   13475           2 :                 surf.Width *= 0.75;
   13476             : 
   13477           2 :                 Xp = surf.Vertex(1).x - BaseXLLC;
   13478           2 :                 Yp = surf.Vertex(1).y - BaseYLLC;
   13479           2 :                 Zp = surf.Vertex(1).z - BaseZLLC;
   13480           2 :                 state.dataSurfaceGeometry->Xpsv(1) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13481           2 :                 state.dataSurfaceGeometry->Ypsv(1) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13482           2 :                 state.dataSurfaceGeometry->Zpsv(1) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13483             : 
   13484           2 :                 Xp = surf.Vertex(3).x - BaseXLLC;
   13485           2 :                 Yp = surf.Vertex(3).y - BaseYLLC;
   13486           2 :                 Zp = surf.Vertex(3).z - BaseZLLC;
   13487           2 :                 state.dataSurfaceGeometry->Xpsv(3) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13488           2 :                 state.dataSurfaceGeometry->Ypsv(3) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13489           2 :                 state.dataSurfaceGeometry->Zpsv(3) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13490           2 :             } break;
   13491           0 :             case SurfaceShape::RectangularOverhang: {
   13492           0 :                 Xp = surf.Vertex(2).x - BaseXLLC;
   13493           0 :                 Yp = surf.Vertex(2).y - BaseYLLC;
   13494           0 :                 Zp = surf.Vertex(2).z - BaseZLLC;
   13495           0 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13496           0 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13497           0 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13498           0 :                 TVect = surf.Vertex(3) - surf.Vertex(2);
   13499           0 :                 ThisWidth = VecLength(TVect);
   13500           0 :                 TVect = surf.Vertex(2) - surf.Vertex(1);
   13501           0 :                 ThisHeight = VecLength(TVect);
   13502           0 :                 surf.Width = ThisWidth;
   13503           0 :                 surf.Height = ThisHeight;
   13504           0 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13505           0 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13506           0 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC + surf.Width;
   13507           0 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC + surf.Width;
   13508           0 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC;
   13509           0 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC;
   13510           0 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC;
   13511           0 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC;
   13512           0 :                 state.dataSurfaceGeometry->Zpsv(1) = surf.Height;
   13513           0 :                 state.dataSurfaceGeometry->Zpsv(4) = surf.Height;
   13514           0 :                 state.dataSurfaceGeometry->Zpsv(2) = 0.0;
   13515           0 :                 state.dataSurfaceGeometry->Zpsv(3) = 0.0;
   13516           0 :             } break;
   13517           0 :             case SurfaceShape::RectangularLeftFin: {
   13518           0 :                 Xp = surf.Vertex(2).x - BaseXLLC;
   13519           0 :                 Yp = surf.Vertex(2).y - BaseYLLC;
   13520           0 :                 Zp = surf.Vertex(2).z - BaseZLLC;
   13521           0 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13522           0 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13523           0 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13524           0 :                 TVect = surf.Vertex(3) - surf.Vertex(2);
   13525           0 :                 ThisWidth = VecLength(TVect);
   13526           0 :                 TVect = surf.Vertex(2) - surf.Vertex(1);
   13527           0 :                 ThisHeight = VecLength(TVect);
   13528           0 :                 surf.Width = ThisWidth;
   13529           0 :                 surf.Height = ThisHeight;
   13530           0 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13531           0 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13532           0 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC;
   13533           0 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC;
   13534           0 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC;
   13535           0 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC;
   13536           0 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC + surf.Width;
   13537           0 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC + surf.Width;
   13538           0 :                 state.dataSurfaceGeometry->Zpsv(1) = surf.Height;
   13539           0 :                 state.dataSurfaceGeometry->Zpsv(4) = surf.Height;
   13540           0 :                 state.dataSurfaceGeometry->Zpsv(2) = 0.0;
   13541           0 :                 state.dataSurfaceGeometry->Zpsv(3) = 0.0;
   13542           0 :             } break;
   13543           0 :             case SurfaceShape::RectangularRightFin: {
   13544           0 :                 Xp = surf.Vertex(2).x - BaseXLLC;
   13545           0 :                 Yp = surf.Vertex(2).y - BaseYLLC;
   13546           0 :                 Zp = surf.Vertex(2).z - BaseZLLC;
   13547           0 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   13548           0 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   13549           0 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   13550           0 :                 TVect = surf.Vertex(3) - surf.Vertex(2);
   13551           0 :                 ThisWidth = VecLength(TVect);
   13552           0 :                 TVect = surf.Vertex(2) - surf.Vertex(1);
   13553           0 :                 ThisHeight = VecLength(TVect);
   13554           0 :                 surf.Width = ThisWidth;
   13555           0 :                 surf.Height = ThisHeight;
   13556           0 :                 state.dataSurfaceGeometry->Xpsv(1) = XLLC;
   13557           0 :                 state.dataSurfaceGeometry->Xpsv(2) = XLLC;
   13558           0 :                 state.dataSurfaceGeometry->Xpsv(3) = XLLC;
   13559           0 :                 state.dataSurfaceGeometry->Xpsv(4) = XLLC;
   13560           0 :                 state.dataSurfaceGeometry->Ypsv(1) = YLLC + surf.Width;
   13561           0 :                 state.dataSurfaceGeometry->Ypsv(2) = YLLC + surf.Width;
   13562           0 :                 state.dataSurfaceGeometry->Ypsv(3) = YLLC;
   13563           0 :                 state.dataSurfaceGeometry->Ypsv(4) = YLLC;
   13564           0 :                 state.dataSurfaceGeometry->Zpsv(1) = surf.Height;
   13565           0 :                 state.dataSurfaceGeometry->Zpsv(4) = surf.Height;
   13566           0 :                 state.dataSurfaceGeometry->Zpsv(2) = 0.0;
   13567           0 :                 state.dataSurfaceGeometry->Zpsv(3) = 0.0;
   13568           0 :             } break;
   13569           0 :             default: {
   13570             :                 // Error Condition
   13571           0 :                 ShowSevereError(state, format("{}Incorrect surface shape number.", RoutineName), OptionalOutputFileRef{state.files.eso});
   13572           0 :                 ShowContinueError(state, "Please notify EnergyPlus support of this error and send input file.");
   13573           0 :                 ErrorInSurface = true;
   13574           0 :             } break;
   13575             :             }
   13576             : 
   13577       33478 :             for (n = 1; n <= surf.Sides; ++n) {
   13578             :                 // if less than 1/10 inch
   13579       26782 :                 state.dataSurfaceGeometry->Xpsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Xpsv(n)) / 10000.0;
   13580       26782 :                 if (std::abs(state.dataSurfaceGeometry->Xpsv(n)) < 0.0025) state.dataSurfaceGeometry->Xpsv(n) = 0.0;
   13581       26782 :                 state.dataSurfaceGeometry->Ypsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Ypsv(n)) / 10000.0;
   13582       26782 :                 if (std::abs(state.dataSurfaceGeometry->Ypsv(n)) < 0.0025) state.dataSurfaceGeometry->Ypsv(n) = 0.0;
   13583       26782 :                 state.dataSurfaceGeometry->Zpsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Zpsv(n)) / 10000.0;
   13584       26782 :                 if (std::abs(state.dataSurfaceGeometry->Zpsv(n)) < 0.0025) state.dataSurfaceGeometry->Zpsv(n) = 0.0;
   13585             :             }
   13586             : 
   13587        6696 :             surf.Shape = ThisShape;
   13588             : 
   13589             :         } // End of check if ThisSurf is a base surface
   13590             : 
   13591       43646 :         if (ErrorInSurface) {
   13592           0 :             ErrorsFound = true;
   13593           0 :             return;
   13594             :         }
   13595             : 
   13596             :         // Transfer to XV,YV,ZV arrays
   13597             : 
   13598       43646 :         state.dataSurface->ShadeV(ThisSurf).NVert = surf.Sides;
   13599       43646 :         state.dataSurface->ShadeV(ThisSurf).XV.allocate(surf.Sides);
   13600       43646 :         state.dataSurface->ShadeV(ThisSurf).YV.allocate(surf.Sides);
   13601       43646 :         state.dataSurface->ShadeV(ThisSurf).ZV.allocate(surf.Sides);
   13602             : 
   13603      219071 :         for (n = 1; n <= surf.Sides; ++n) {
   13604             :             // if less than 1/10 inch
   13605      175425 :             state.dataSurface->ShadeV(ThisSurf).XV(n) = state.dataSurfaceGeometry->Xpsv(n);
   13606      175425 :             state.dataSurface->ShadeV(ThisSurf).YV(n) = state.dataSurfaceGeometry->Ypsv(n);
   13607      175425 :             state.dataSurface->ShadeV(ThisSurf).ZV(n) = state.dataSurfaceGeometry->Zpsv(n);
   13608             :         }
   13609             : 
   13610             :         // Process Surfaces According to Type of Coordinate Origin.
   13611       43646 :         if (BaseSurface) {
   13612             : 
   13613             :             // General Surfaces:
   13614       36950 :             CalcCoordinateTransformation(state, ThisSurf, CoordinateTransVector); // X00,Y00,Z00,X,Y,Z,A)    ! Compute Coordinate Transformation
   13615             : 
   13616             :             // RECORD DIRECTION COSINES.
   13617       36950 :             if (HeatTransSurf) { // This is a general surface but not detached shading surface
   13618             : 
   13619             :                 // RECORD COORDINATE TRANSFORMATION FOR BASE SURFACES.
   13620       36932 :                 state.dataSurface->X0(ThisBaseSurface) = CoordinateTransVector.x;
   13621       36932 :                 state.dataSurface->Y0(ThisBaseSurface) = CoordinateTransVector.y;
   13622       36932 :                 state.dataSurface->Z0(ThisBaseSurface) = CoordinateTransVector.z;
   13623             : 
   13624             :                 // COMPUTE INVERSE TRANSFORMATION.
   13625       36932 :                 X1 = state.dataSurfaceGeometry->Xpsv(2) - CoordinateTransVector.x;
   13626       36932 :                 Y1 = state.dataSurfaceGeometry->Ypsv(2) - CoordinateTransVector.y;
   13627       36932 :                 Z1 = state.dataSurfaceGeometry->Zpsv(2) - CoordinateTransVector.z;
   13628             :                 // Store the relative coordinate shift values for later use by any subsurfaces
   13629       73864 :                 state.dataSurface->Surface(ThisBaseSurface).XShift = state.dataSurface->Surface(ThisBaseSurface).lcsx.x * X1 +
   13630       36932 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsx.y * Y1 +
   13631       36932 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsx.z * Z1;
   13632       73864 :                 state.dataSurface->Surface(ThisBaseSurface).YShift = state.dataSurface->Surface(ThisBaseSurface).lcsy.x * X1 +
   13633       36932 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsy.y * Y1 +
   13634       36932 :                                                                      state.dataSurface->Surface(ThisBaseSurface).lcsy.z * Z1;
   13635       36932 :                 state.dataSurface->Surface(ThisBaseSurface).VerticesProcessed = true;
   13636             :             }
   13637             : 
   13638             :             // SUBSURFACES: (Surface(ThisSurf)%BaseSurf /= ThisSurf)
   13639             :         } else {
   13640             :             // WINDOWS OR DOORS:
   13641             : 
   13642             :             // SHIFT RELATIVE COORDINATES FROM LOWER LEFT CORNER TO ORIGIN DEFINED
   13643             :             // BY CTRAN AND SET DIRECTION COSINES SAME AS BASE SURFACE.
   13644        6696 :             if (!state.dataSurface->Surface(ThisBaseSurface).VerticesProcessed) {
   13645             : 
   13646           0 :                 if (surf.IsAirBoundarySurf) {
   13647           0 :                     ProcessSurfaceVertices(state, ThisBaseSurface, ErrorsFound);
   13648             :                 } else {
   13649             : 
   13650           0 :                     ShowSevereError(state, format("{}Developer error for Subsurface={}", RoutineName, surf.Name));
   13651           0 :                     ShowContinueError(state,
   13652           0 :                                       format("Base surface={} vertices must be processed before any subsurfaces.",
   13653           0 :                                              state.dataSurface->Surface(ThisBaseSurface).Name));
   13654           0 :                     ShowFatalError(state, std::string{RoutineName});
   13655             :                 }
   13656             :             }
   13657             : 
   13658       33478 :             for (n = 1; n <= surf.Sides; ++n) {
   13659       26782 :                 state.dataSurface->ShadeV(ThisSurf).XV(n) += state.dataSurface->Surface(ThisBaseSurface).XShift;
   13660       26782 :                 state.dataSurface->ShadeV(ThisSurf).YV(n) += state.dataSurface->Surface(ThisBaseSurface).YShift;
   13661             :             }
   13662             :         }
   13663             : 
   13664       43646 :         if (ErrorInSurface) {
   13665           0 :             ErrorsFound = true;
   13666             :         }
   13667       43646 :     }
   13668             : 
   13669       36950 :     void CalcCoordinateTransformation(EnergyPlusData &state,
   13670             :                                       int const SurfNum,            // Surface Number
   13671             :                                       Vector &CompCoordTranslVector // Coordinate Translation Vector
   13672             :     )
   13673             :     {
   13674             :         // SUBROUTINE INFORMATION:
   13675             :         //       AUTHOR         George Walton, BLAST
   13676             :         //       DATE WRITTEN   August 1976
   13677             :         //       MODIFIED       LKL, May 2004 -- >4 sided polygons
   13678             :         //       RE-ENGINEERED  Yes
   13679             : 
   13680             :         // PURPOSE OF THIS SUBROUTINE:
   13681             :         // This subroutine develops a coordinate transformation such that the X-axis goes
   13682             :         // through points 2 and 3 and the Y-axis goes through point 1
   13683             :         // of a plane figure in 3-d space.
   13684             : 
   13685             :         // METHODOLOGY EMPLOYED:
   13686             :         // na
   13687             : 
   13688             :         // REFERENCES:
   13689             :         // 'NECAP' - NASA'S Energy-Cost Analysis Program
   13690             : 
   13691             :         // Using/Aliasing
   13692             :         using namespace Vectors;
   13693             : 
   13694             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   13695             :         int I;        // Loop Control
   13696             :         Real64 Gamma; // Intermediate Result
   13697             :         Real64 DotSelfX23;
   13698             : 
   13699             :         // Object Data
   13700       36950 :         Vector x21;
   13701       36950 :         Vector x23;
   13702             : 
   13703             :         // Determine Components of the Coordinate Translation Vector.
   13704       36950 :         auto const &surf = state.dataSurface->Surface(SurfNum);
   13705             : 
   13706       36950 :         x21 = surf.Vertex(2) - surf.Vertex(1);
   13707       36950 :         x23 = surf.Vertex(2) - surf.Vertex(3);
   13708             : 
   13709       36950 :         DotSelfX23 = magnitude_squared(x23);
   13710             : 
   13711       36950 :         if (DotSelfX23 <= Constant::OneMillionth) {
   13712           0 :             ShowSevereError(state, format("CalcCoordinateTransformation: Invalid dot product, surface=\"{}\":", surf.Name));
   13713           0 :             for (I = 1; I <= surf.Sides; ++I) {
   13714           0 :                 auto const &point = surf.Vertex(I);
   13715           0 :                 ShowContinueError(state, format(" ({:8.3F},{:8.3F},{:8.3F})", point.x, point.y, point.z));
   13716             :             }
   13717           0 :             ShowFatalError(
   13718           0 :                 state, "CalcCoordinateTransformation: Program terminates due to preceding condition.", OptionalOutputFileRef{state.files.eso});
   13719           0 :             return;
   13720             :         }
   13721             : 
   13722       36950 :         Gamma = dot(x21, x23) / magnitude_squared(x23);
   13723             : 
   13724       36950 :         CompCoordTranslVector = surf.Vertex(2) + Gamma * (surf.Vertex(3) - surf.Vertex(2));
   13725       36950 :     }
   13726             : 
   13727          18 :     void CreateShadedWindowConstruction(EnergyPlusData &state,
   13728             :                                         int const SurfNum,          // Surface number
   13729             :                                         int const WSCPtr,           // Pointer to WindowShadingControl for SurfNum
   13730             :                                         int const ShDevNum,         // Shading device material number for WSCptr
   13731             :                                         int const shadeControlIndex // index to the Surface().windowShadingControlList,
   13732             :                                                                     // Surface().shadedConstructionList, and Surface().shadedStormWinConstructionList
   13733             :     )
   13734             :     {
   13735             :         // SUBROUTINE INFORMATION:
   13736             :         //       AUTHOR         Fred Winkelmann
   13737             :         //       DATE WRITTEN   Nov 2001
   13738             :         //       MODIFIED       na
   13739             :         //       RE-ENGINEERED  na
   13740             : 
   13741             :         // PURPOSE OF THIS SUBROUTINE:
   13742             :         // Creates a shaded window construction for windows whose WindowShadingControl
   13743             :         // has a shading device specified instead of a shaded construction
   13744             : 
   13745             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   13746             :         int ConstrNum;            // Number of unshaded construction
   13747             :         int ConstrNewSh;          // Number of shaded construction that is created
   13748          18 :         std::string ShDevName;    // Shading device material name
   13749          18 :         std::string ConstrName;   // Unshaded construction name
   13750          18 :         std::string ConstrNameSh; // Shaded construction name
   13751             :         int TotLayersOld;         // Total layers in old (unshaded) construction
   13752             :         int TotLayersNew;         // Total layers in new (shaded) construction
   13753             :         //  INTEGER :: loop                            ! DO loop index
   13754             : 
   13755          18 :         ShDevName = state.dataMaterial->Material(ShDevNum)->Name;
   13756          18 :         ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
   13757          18 :         ConstrName = state.dataConstruction->Construct(ConstrNum).Name;
   13758          18 :         if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
   13759          18 :             ConstrNameSh = ConstrName + ':' + ShDevName + ":INT";
   13760             :         } else {
   13761           0 :             ConstrNameSh = ConstrName + ':' + ShDevName + ":EXT";
   13762             :         }
   13763             : 
   13764             :         // If this construction name already exists, set the surface's shaded construction number to it
   13765             : 
   13766          18 :         ConstrNewSh = Util::FindItemInList(ConstrNameSh, state.dataConstruction->Construct);
   13767             : 
   13768          18 :         if (ConstrNewSh > 0) {
   13769           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex] = ConstrNewSh;
   13770           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNewSh; // set the active to the current for now
   13771             :         } else {
   13772             : 
   13773             :             // Create new construction
   13774             : 
   13775          18 :             ConstrNewSh = state.dataHeatBal->TotConstructs + 1;
   13776          18 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex] = ConstrNewSh;
   13777          18 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNewSh; // set the active to the current for now
   13778          18 :             state.dataHeatBal->TotConstructs = ConstrNewSh;
   13779          18 :             state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
   13780          18 :             state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
   13781          18 :             state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs) = 0.0;
   13782          18 :             state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
   13783          18 :             state.dataHeatBal->NominalU(state.dataHeatBal->TotConstructs) = 0.0;
   13784          18 :             state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
   13785          18 :             state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
   13786             : 
   13787          18 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).setArraysBasedOnMaxSolidWinLayers(state);
   13788             : 
   13789          18 :             TotLayersOld = state.dataConstruction->Construct(ConstrNum).TotLayers;
   13790          18 :             TotLayersNew = TotLayersOld + 1;
   13791             : 
   13792          18 :             state.dataConstruction->Construct(ConstrNewSh).LayerPoint = 0;
   13793             : 
   13794          18 :             auto const *thisMaterialSh = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(ShDevNum));
   13795          18 :             auto &thisConstructNewSh = state.dataConstruction->Construct(ConstrNewSh);
   13796          18 :             if (state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::IntShade ||
   13797           0 :                 state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::IntBlind) {
   13798             :                 // Interior shading device
   13799          18 :                 thisConstructNewSh.LayerPoint({1, TotLayersOld}) = state.dataConstruction->Construct(ConstrNum).LayerPoint({1, TotLayersOld});
   13800          18 :                 thisConstructNewSh.LayerPoint(TotLayersNew) = ShDevNum;
   13801          18 :                 thisConstructNewSh.InsideAbsorpSolar = thisMaterialSh->AbsorpSolar;
   13802          18 :                 auto const *thisMaterialShLayer1 = dynamic_cast<const Material::MaterialChild *>(
   13803          18 :                     state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1)));
   13804          18 :                 thisConstructNewSh.OutsideAbsorpSolar = thisMaterialShLayer1->AbsorpSolar;
   13805          18 :                 thisConstructNewSh.OutsideAbsorpThermal = thisMaterialShLayer1->AbsorpThermalFront;
   13806             :             } else {
   13807             :                 // Exterior shading device
   13808           0 :                 thisConstructNewSh.LayerPoint(1) = ShDevNum;
   13809           0 :                 thisConstructNewSh.LayerPoint({2, TotLayersNew}) = state.dataConstruction->Construct(ConstrNum).LayerPoint({1, TotLayersOld});
   13810           0 :                 auto const *thisMaterialShInside = dynamic_cast<const Material::MaterialChild *>(
   13811           0 :                     state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(TotLayersNew)));
   13812           0 :                 thisConstructNewSh.InsideAbsorpSolar = thisMaterialShInside->AbsorpSolar;
   13813           0 :                 thisConstructNewSh.OutsideAbsorpSolar = thisMaterialSh->AbsorpSolar;
   13814           0 :                 thisConstructNewSh.OutsideAbsorpThermal = thisMaterialSh->AbsorpThermalFront;
   13815             :             }
   13816             :             // The following InsideAbsorpThermal applies only to inside glass; it is corrected
   13817             :             //  later in InitGlassOpticalCalculations if construction has inside shade or blind.
   13818          18 :             thisConstructNewSh.InsideAbsorpThermal =
   13819          18 :                 dynamic_cast<Material::MaterialChild *>(
   13820          18 :                     state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayersOld)))
   13821          18 :                     ->AbsorpThermalBack;
   13822          18 :             thisConstructNewSh.OutsideRoughness = Material::SurfaceRoughness::VerySmooth;
   13823          18 :             thisConstructNewSh.DayltPropPtr = 0;
   13824          18 :             thisConstructNewSh.CTFCross.fill(0.0);
   13825          18 :             thisConstructNewSh.CTFFlux.fill(0.0);
   13826          18 :             thisConstructNewSh.CTFInside.fill(0.0);
   13827          18 :             thisConstructNewSh.CTFOutside.fill(0.0);
   13828          18 :             thisConstructNewSh.CTFSourceIn.fill(0.0);
   13829          18 :             thisConstructNewSh.CTFSourceOut.fill(0.0);
   13830          18 :             thisConstructNewSh.CTFTimeStep = 0.0;
   13831          18 :             thisConstructNewSh.CTFTSourceOut.fill(0.0);
   13832          18 :             thisConstructNewSh.CTFTSourceIn.fill(0.0);
   13833          18 :             thisConstructNewSh.CTFTSourceQ.fill(0.0);
   13834          18 :             thisConstructNewSh.CTFTUserOut.fill(0.0);
   13835          18 :             thisConstructNewSh.CTFTUserIn.fill(0.0);
   13836          18 :             thisConstructNewSh.CTFTUserSource.fill(0.0);
   13837          18 :             thisConstructNewSh.NumHistories = 0;
   13838          18 :             thisConstructNewSh.NumCTFTerms = 0;
   13839          18 :             thisConstructNewSh.UValue = 0.0;
   13840          18 :             thisConstructNewSh.SourceSinkPresent = false;
   13841          18 :             thisConstructNewSh.SolutionDimensions = 0;
   13842          18 :             thisConstructNewSh.SourceAfterLayer = 0;
   13843          18 :             thisConstructNewSh.TempAfterLayer = 0;
   13844          18 :             thisConstructNewSh.ThicknessPerpend = 0.0;
   13845          18 :             thisConstructNewSh.AbsDiff = 0.0;
   13846          18 :             thisConstructNewSh.AbsDiffBack = 0.0;
   13847          18 :             thisConstructNewSh.AbsDiffShade = 0.0;
   13848          18 :             thisConstructNewSh.AbsDiffBackShade = 0.0;
   13849          18 :             thisConstructNewSh.ShadeAbsorpThermal = 0.0;
   13850          18 :             thisConstructNewSh.AbsBeamShadeCoef = 0.0;
   13851          18 :             thisConstructNewSh.TransDiff = 0.0;
   13852          18 :             thisConstructNewSh.TransDiffVis = 0.0;
   13853          18 :             thisConstructNewSh.ReflectSolDiffBack = 0.0;
   13854          18 :             thisConstructNewSh.ReflectSolDiffFront = 0.0;
   13855          18 :             thisConstructNewSh.ReflectVisDiffBack = 0.0;
   13856          18 :             thisConstructNewSh.ReflectVisDiffFront = 0.0;
   13857          18 :             thisConstructNewSh.TransSolBeamCoef = 0.0;
   13858          18 :             thisConstructNewSh.TransVisBeamCoef = 0.0;
   13859          18 :             thisConstructNewSh.ReflSolBeamFrontCoef = 0.0;
   13860          18 :             thisConstructNewSh.ReflSolBeamBackCoef = 0.0;
   13861          18 :             thisConstructNewSh.W5FrameDivider = 0;
   13862          18 :             thisConstructNewSh.FromWindow5DataFile = false;
   13863             : 
   13864          18 :             thisConstructNewSh.Name = ConstrNameSh;
   13865          18 :             thisConstructNewSh.TotLayers = TotLayersNew;
   13866          18 :             thisConstructNewSh.TotSolidLayers = state.dataConstruction->Construct(ConstrNum).TotSolidLayers + 1;
   13867          18 :             thisConstructNewSh.TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
   13868          18 :             thisConstructNewSh.TypeIsWindow = true;
   13869          18 :             thisConstructNewSh.IsUsed = true;
   13870             : 
   13871         144 :             for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
   13872         882 :                 for (int index = 1; index <= DataSurfaces::MaxPolyCoeff; ++index) {
   13873         756 :                     thisConstructNewSh.AbsBeamCoef(Layer)(index) = 0.0;
   13874         756 :                     thisConstructNewSh.AbsBeamBackCoef(Layer)(index) = 0.0;
   13875             :                 }
   13876             :             }
   13877             :         }
   13878          18 :     }
   13879             : 
   13880           1 :     void CreateStormWindowConstructions(EnergyPlusData &state)
   13881             :     {
   13882             :         // For windows with an associated StormWindow object, creates a construction
   13883             :         // consisting of the base construction plus a storm window and air gap on the outside.
   13884             :         // If the window has an interior or between-glass shade/blind, also creates a
   13885             :         // construction consisting of the storm window added to the shaded construction.
   13886           1 :         DisplayString(state, "Creating Storm Window Constructions");
   13887             : 
   13888           2 :         for (int StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
   13889           1 :             int SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum; // Surface number
   13890           1 :             auto &surf = state.dataSurface->Surface(SurfNum);
   13891           1 :             int ConstrNum = surf.Construction; // Number of unshaded construction
   13892             :             // Fatal error if base construction has more than three glass layers
   13893           1 :             if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers > 3) {
   13894           0 :                 ShowFatalError(state, format("Window={} has more than 3 glass layers; a storm window cannot be applied.", surf.Name));
   13895             :             }
   13896             : 
   13897             :             // create unshaded construction with storm window
   13898           1 :             const std::string ChrNum = fmt::to_string(StormWinNum);
   13899           1 :             std::string ConstrNameSt = "BARECONSTRUCTIONWITHSTORMWIN:" + ChrNum; // Name of unshaded construction with storm window
   13900             :             // If this construction name already exists, set the surface's storm window construction number to it
   13901           1 :             int ConstrNewSt = Util::FindItemInList(ConstrNameSt,
   13902           1 :                                                    state.dataConstruction->Construct,
   13903           1 :                                                    state.dataHeatBal->TotConstructs); // Number of unshaded storm window construction that is created
   13904             :             // If necessary, create new material corresponding to the air layer between the storm winddow and the rest of the window
   13905           1 :             int MatNewStAir = createAirMaterialFromDistance(state, state.dataSurface->StormWindow(StormWinNum).StormWinDistance, "AIR:STORMWIN:");
   13906           1 :             if (ConstrNewSt == 0) {
   13907           1 :                 ConstrNewSt = createConstructionWithStorm(
   13908           1 :                     state, ConstrNum, ConstrNameSt, state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum, MatNewStAir);
   13909             :             }
   13910           1 :             state.dataSurface->SurfWinStormWinConstr(SurfNum) = ConstrNewSt;
   13911             : 
   13912             :             // create shaded constructions with storm window
   13913           1 :             surf.shadedStormWinConstructionList.resize(surf.shadedConstructionList.size(),
   13914           1 :                                                        0); // make the shaded storm window size the same size as the number of shaded constructions
   13915           1 :             for (std::size_t iConstruction = 0; iConstruction < surf.shadedConstructionList.size(); ++iConstruction) {
   13916           0 :                 int curConstruction = surf.shadedConstructionList[iConstruction];
   13917             :                 // Set ShAndSt, which is true if the window has a shaded construction to which a storm window
   13918             :                 // can be added. (A storm window can be added if there is an interior shade or blind and up to three
   13919             :                 // glass layers, or there is a between-glass shade or blind and two glass layers.)
   13920           0 :                 bool ShAndSt = false; // True if unshaded and shaded window can have a storm window
   13921           0 :                 std::string ConstrNameSh = state.dataConstruction->Construct(curConstruction).Name; // Name of original shaded window construction
   13922           0 :                 int TotLayers = state.dataConstruction->Construct(curConstruction).TotLayers;       // Total layers in a construction
   13923           0 :                 int MatIntSh = state.dataConstruction->Construct(curConstruction).LayerPoint(TotLayers); // Material number of interior shade or blind
   13924           0 :                 int MatBetweenGlassSh = 0; // Material number of between-glass shade or blind
   13925           0 :                 if (TotLayers == 5) MatBetweenGlassSh = state.dataConstruction->Construct(curConstruction).LayerPoint(3);
   13926           0 :                 if (state.dataConstruction->Construct(curConstruction).TotGlassLayers <= 3 &&
   13927           0 :                     (state.dataMaterial->Material(MatIntSh)->group == Material::Group::Shade ||
   13928           0 :                      state.dataMaterial->Material(MatIntSh)->group == Material::Group::WindowBlind))
   13929           0 :                     ShAndSt = true;
   13930           0 :                 if (MatBetweenGlassSh > 0) {
   13931           0 :                     if (state.dataMaterial->Material(MatBetweenGlassSh)->group == Material::Group::Shade ||
   13932           0 :                         state.dataMaterial->Material(MatBetweenGlassSh)->group == Material::Group::WindowBlind) {
   13933           0 :                         ShAndSt = true;
   13934             :                     } else {
   13935           0 :                         ShowContinueError(state, format("Window={} has a shaded construction to which a storm window cannot be applied.", surf.Name));
   13936           0 :                         ShowContinueError(state, "Storm windows can only be applied to shaded constructions that:");
   13937           0 :                         ShowContinueError(state, "have an interior shade or blind and up to three glass layers, or");
   13938           0 :                         ShowContinueError(state, "have a between-glass shade or blind and two glass layers.");
   13939           0 :                         ShowFatalError(state, "EnergyPlus is exiting due to reason stated above.");
   13940             :                     }
   13941             :                 }
   13942           0 :                 if (ShAndSt) {
   13943           0 :                     auto &surf = state.dataSurface->Surface(SurfNum);
   13944           0 :                     std::string ConstrNameStSh = "SHADEDCONSTRUCTIONWITHSTORMWIN:" + state.dataConstruction->Construct(iConstruction).Name + ":" +
   13945           0 :                                                  ChrNum; // Name of shaded construction with storm window
   13946           0 :                     int ConstrNewStSh = createConstructionWithStorm(
   13947           0 :                         state, ConstrNum, ConstrNameStSh, state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum, MatNewStAir);
   13948           0 :                     surf.shadedStormWinConstructionList[iConstruction] = ConstrNewStSh; // put in same index as the shaded constuction
   13949           0 :                 }
   13950           0 :             } // end of loop for shaded constructions
   13951           1 :         }     // end of loop over storm window objects
   13952           1 :     }
   13953             : 
   13954           1 :     int createAirMaterialFromDistance(EnergyPlusData &state, Real64 distance, std::string_view namePrefix)
   13955             :     {
   13956           1 :         int mmDistance = int(1000 * distance); // Thickness of air gap in mm (usually between storm window and rest of window)
   13957           1 :         std::string MatNameStAir = format("{}{}MM", namePrefix, mmDistance); // Name of created air layer material
   13958           1 :         int newAirMaterial = Util::FindItemInPtrList(MatNameStAir, state.dataMaterial->Material, state.dataMaterial->TotMaterials);
   13959           1 :         if (newAirMaterial == 0) {
   13960             :             // Create new material
   13961           1 :             state.dataMaterial->TotMaterials = state.dataMaterial->TotMaterials + 1;
   13962           1 :             newAirMaterial = state.dataMaterial->TotMaterials;
   13963           1 :             auto *thisMaterial = new Material::MaterialGasMix;
   13964           1 :             state.dataMaterial->Material.push_back(thisMaterial);
   13965           1 :             state.dataHeatBal->NominalR.redimension(state.dataMaterial->TotMaterials);
   13966           1 :             thisMaterial->Name = MatNameStAir;
   13967           1 :             thisMaterial->group = Material::Group::WindowGas;
   13968           1 :             thisMaterial->Roughness = Material::SurfaceRoughness::MediumRough;
   13969           1 :             thisMaterial->Conductivity = 0.0;
   13970           1 :             thisMaterial->Density = 0.0;
   13971             :             // thisMaterial->IsoMoistCap = 0.0;
   13972             :             // thisMaterial->Porosity = 0.0;
   13973           1 :             thisMaterial->Resistance = 0.0;
   13974           1 :             thisMaterial->SpecHeat = 0.0;
   13975             :             // thisMaterial->ThermGradCoef = 0.0;
   13976           1 :             thisMaterial->Thickness = distance;
   13977             :             // thisMaterial->VaporDiffus = 0.0;
   13978             :             // thisMaterial->GlassSpectralDataPtr = 0;
   13979           1 :             thisMaterial->numGases = 1;
   13980           1 :             thisMaterial->gases[0] = Material::gases[(int)Material::GasType::Air];
   13981           1 :             thisMaterial->gasFracts[0] = 1.0;
   13982           1 :             thisMaterial->AbsorpSolar = 0.0;
   13983           1 :             thisMaterial->AbsorpThermal = 0.0;
   13984           1 :             thisMaterial->AbsorpVisible = 0.0;
   13985           1 :             thisMaterial->Trans = 0.0;
   13986           1 :             thisMaterial->TransVis = 0.0;
   13987             :             // thisMaterial->GlassTransDirtFactor = 0.0;
   13988             :             // thisMaterial->ReflectShade = 0.0;
   13989             :             // thisMaterial->ReflectShadeVis = 0.0;
   13990             :             // thisMaterial->AbsorpThermalBack = 0.0;
   13991             :             // thisMaterial->AbsorpThermalFront = 0.0;
   13992             :             // thisMaterial->ReflectSolBeamBack = 0.0;
   13993             :             // thisMaterial->ReflectSolBeamFront = 0.0;
   13994             :             // thisMaterial->ReflectSolDiffBack = 0.0;
   13995             :             // thisMaterial->ReflectSolDiffFront = 0.0;
   13996             :             // thisMaterial->ReflectVisBeamBack = 0.0;
   13997             :             // thisMaterial->ReflectVisBeamFront = 0.0;
   13998             :             // thisMaterial->ReflectVisDiffBack = 0.0;
   13999             :             // thisMaterial->ReflectVisDiffFront = 0.0;
   14000             :             // thisMaterial->TransSolBeam = 0.0;
   14001             :             // thisMaterial->TransThermal = 0.0;
   14002             :             // thisMaterial->TransVisBeam = 0.0;
   14003             :             // thisMaterial->BlindDataPtr = 0;
   14004             :             // thisMaterial->WinShadeToGlassDist = 0.0;
   14005             :             // thisMaterial->WinShadeTopOpeningMult = 0.0;
   14006             :             // thisMaterial->WinShadeBottomOpeningMult = 0.0;
   14007             :             // thisMaterial->WinShadeLeftOpeningMult = 0.0;
   14008             :             // thisMaterial->WinShadeRightOpeningMult = 0.0;
   14009             :             // thisMaterial->WinShadeAirFlowPermeability = 0.0;
   14010             :         }
   14011           1 :         return (newAirMaterial);
   14012           1 :     }
   14013             : 
   14014             :     // create a new construction with storm based on an old construction and storm and gap materials
   14015           1 :     int createConstructionWithStorm(EnergyPlusData &state, int oldConstruction, std::string name, int stormMaterial, int gapMaterial)
   14016             :     {
   14017           1 :         int newConstruct = Util::FindItemInList(name,
   14018           1 :                                                 state.dataConstruction->Construct,
   14019           1 :                                                 state.dataHeatBal->TotConstructs); // Number of shaded storm window construction that is created
   14020           1 :         if (newConstruct == 0) {
   14021           1 :             state.dataHeatBal->TotConstructs = state.dataHeatBal->TotConstructs + 1;
   14022           1 :             newConstruct = state.dataHeatBal->TotConstructs;
   14023           1 :             state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
   14024           1 :             state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
   14025           1 :             state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
   14026           1 :             state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
   14027           1 :             state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
   14028             : 
   14029           1 :             auto &thisConstruct = state.dataConstruction->Construct(state.dataHeatBal->TotConstructs);
   14030             :             // these Construct arrays dimensioned based on MaxSolidWinLayers
   14031           1 :             thisConstruct.setArraysBasedOnMaxSolidWinLayers(state);
   14032             : 
   14033           1 :             int TotLayersOld = state.dataConstruction->Construct(oldConstruction).TotLayers;
   14034           1 :             thisConstruct.LayerPoint({1, Construction::MaxLayersInConstruct}) = 0;
   14035           1 :             thisConstruct.LayerPoint(1) = stormMaterial;
   14036           1 :             thisConstruct.LayerPoint(2) = gapMaterial;
   14037           1 :             thisConstruct.LayerPoint({3, TotLayersOld + 2}) = state.dataConstruction->Construct(oldConstruction).LayerPoint({1, TotLayersOld});
   14038           1 :             thisConstruct.Name = name;
   14039           1 :             thisConstruct.TotLayers = TotLayersOld + 2;
   14040           1 :             thisConstruct.TotSolidLayers = state.dataConstruction->Construct(oldConstruction).TotSolidLayers + 1;
   14041           1 :             thisConstruct.TotGlassLayers = state.dataConstruction->Construct(oldConstruction).TotGlassLayers + 1;
   14042           1 :             thisConstruct.TypeIsWindow = true;
   14043           1 :             thisConstruct.InsideAbsorpVis = 0.0;
   14044           1 :             thisConstruct.OutsideAbsorpVis = 0.0;
   14045           1 :             thisConstruct.InsideAbsorpSolar = 0.0;
   14046           1 :             thisConstruct.OutsideAbsorpSolar = 0.0;
   14047           1 :             thisConstruct.InsideAbsorpThermal = state.dataConstruction->Construct(oldConstruction).InsideAbsorpThermal;
   14048           1 :             thisConstruct.OutsideAbsorpThermal =
   14049           1 :                 dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(stormMaterial))->AbsorpThermalFront;
   14050           1 :             thisConstruct.OutsideRoughness = Material::SurfaceRoughness::VerySmooth;
   14051           1 :             thisConstruct.DayltPropPtr = 0;
   14052           1 :             thisConstruct.CTFCross.fill(0.0);
   14053           1 :             thisConstruct.CTFFlux.fill(0.0);
   14054           1 :             thisConstruct.CTFInside.fill(0.0);
   14055           1 :             thisConstruct.CTFOutside.fill(0.0);
   14056           1 :             thisConstruct.CTFSourceIn.fill(0.0);
   14057           1 :             thisConstruct.CTFSourceOut.fill(0.0);
   14058           1 :             thisConstruct.CTFTimeStep = 0.0;
   14059           1 :             thisConstruct.CTFTSourceOut.fill(0.0);
   14060           1 :             thisConstruct.CTFTSourceIn.fill(0.0);
   14061           1 :             thisConstruct.CTFTSourceQ.fill(0.0);
   14062           1 :             thisConstruct.CTFTUserOut.fill(0.0);
   14063           1 :             thisConstruct.CTFTUserIn.fill(0.0);
   14064           1 :             thisConstruct.CTFTUserSource.fill(0.0);
   14065           1 :             thisConstruct.NumHistories = 0;
   14066           1 :             thisConstruct.NumCTFTerms = 0;
   14067           1 :             thisConstruct.UValue = 0.0;
   14068           1 :             thisConstruct.SourceSinkPresent = false;
   14069           1 :             thisConstruct.SolutionDimensions = 0;
   14070           1 :             thisConstruct.SourceAfterLayer = 0;
   14071           1 :             thisConstruct.TempAfterLayer = 0;
   14072           1 :             thisConstruct.ThicknessPerpend = 0.0;
   14073           1 :             thisConstruct.AbsDiffIn = 0.0;
   14074           1 :             thisConstruct.AbsDiffOut = 0.0;
   14075           1 :             thisConstruct.AbsDiff = 0.0;
   14076           1 :             thisConstruct.AbsDiffBack = 0.0;
   14077           1 :             thisConstruct.AbsDiffShade = 0.0;
   14078           1 :             thisConstruct.AbsDiffBackShade = 0.0;
   14079           1 :             thisConstruct.ShadeAbsorpThermal = 0.0;
   14080           1 :             thisConstruct.AbsBeamShadeCoef = 0.0;
   14081           1 :             thisConstruct.TransDiff = 0.0;
   14082           1 :             thisConstruct.TransDiffVis = 0.0;
   14083           1 :             thisConstruct.ReflectSolDiffBack = 0.0;
   14084           1 :             thisConstruct.ReflectSolDiffFront = 0.0;
   14085           1 :             thisConstruct.ReflectVisDiffBack = 0.0;
   14086           1 :             thisConstruct.ReflectVisDiffFront = 0.0;
   14087           1 :             thisConstruct.TransSolBeamCoef = 0.0;
   14088           1 :             thisConstruct.TransVisBeamCoef = 0.0;
   14089           1 :             thisConstruct.ReflSolBeamFrontCoef = 0.0;
   14090           1 :             thisConstruct.ReflSolBeamBackCoef = 0.0;
   14091           1 :             thisConstruct.W5FrameDivider = 0;
   14092           1 :             thisConstruct.FromWindow5DataFile = false;
   14093           1 :             thisConstruct.W5FileMullionWidth = 0.0;
   14094           1 :             thisConstruct.W5FileMullionOrientation = DataWindowEquivalentLayer::Orientation::Invalid;
   14095           1 :             thisConstruct.W5FileGlazingSysWidth = 0.0;
   14096           1 :             thisConstruct.W5FileGlazingSysHeight = 0.0;
   14097           8 :             for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
   14098          49 :                 for (int index = 1; index <= DataSurfaces::MaxPolyCoeff; ++index) {
   14099          42 :                     thisConstruct.AbsBeamCoef(Layer)(index) = 0.0;
   14100          42 :                     thisConstruct.AbsBeamBackCoef(Layer)(index) = 0.0;
   14101             :                 }
   14102             :             }
   14103             :         }
   14104           1 :         return (newConstruct);
   14105             :     }
   14106             : 
   14107           8 :     void ModifyWindow(EnergyPlusData &state,
   14108             :                       int const SurfNum,    // SurfNum has construction of glazing system from Window5 Data File;
   14109             :                       bool &ErrorsFound,    // Set to true if errors found
   14110             :                       int &AddedSubSurfaces // Subsurfaces added when window references a
   14111             :     )
   14112             :     {
   14113             :         // SUBROUTINE INFORMATION:
   14114             :         //       AUTHOR         Fred Winkelmann
   14115             :         //       DATE WRITTEN   Feb 2002
   14116             :         //       MODIFIED       June 2004, FCW: SinAzim, CosAzim, SinTilt, CosTilt, OutNormVec, GrossArea
   14117             :         //                       and Perimeter weren't being set for created window for case when
   14118             :         //                       window from Window5DataFile had two different glazing systems. Also,
   14119             :         //                       GrossArea and Perimeter of original window were not being recalculated.
   14120             :         //                      October 2007, LKL: Net area for shading calculations was not being
   14121             :         //                       recalculated.
   14122             :         //       RE-ENGINEERED  na
   14123             : 
   14124             :         // PURPOSE OF THIS SUBROUTINE:
   14125             :         // If a window from the Window5DataFile has one glazing system, modify the
   14126             :         // vertex coordinates of the original window to correspond to the dimensions
   14127             :         // of the glazing system on the Data File.
   14128             :         // If a window from the Window5DataFile has two different glazing systems, split
   14129             :         // the window into two separate windows with different properties and adjust the
   14130             :         // vertices of these windows taking into account the dimensions of the glazing systems
   14131             :         // on the Data File and the width and orientation of the mullion that separates
   14132             :         // the glazing systems.
   14133             : 
   14134             :         // Using/Aliasing
   14135             : 
   14136             :         using namespace Vectors;
   14137             : 
   14138             :         // Locals
   14139             :         // SUBROUTINE ARGUMENT DEFINITIONS:
   14140             :         // If there is a second glazing systme on the Data File, SurfNum+1
   14141             :         // has the construction of the second glazing system.
   14142             : 
   14143             :         // 2-glazing system Window5 data file entry
   14144             : 
   14145             :         // DERIVED TYPE DEFINITIONS:
   14146             : 
   14147             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   14148             :         Real64 H; // Height and width of original window (m)
   14149             :         Real64 W;
   14150             :         // unused1208  REAL(r64)    :: MulWidth                        ! Mullion width (m)
   14151             :         Real64 h1; // height and width of first glazing system (m)
   14152             :         Real64 w1;
   14153             :         // unused1208  REAL(r64)    :: h2,w2                           ! height and width of second glazing system (m)
   14154             :         // unused1208  type (rectangularwindow) :: NewCoord
   14155             :         int IConst;             // Construction number of first glazing system
   14156             :         int IConst2;            // Construction number of second glazing system
   14157           8 :         std::string Const2Name; // Name of construction of second glazing system
   14158             :         // unused1208  REAL(r64)    :: AreaNew                         ! Sum of areas of the two glazing systems (m2)
   14159             : 
   14160             :         struct rectangularwindow
   14161             :         {
   14162             :             // Members
   14163             :             Array1D<Vector> Vertex;
   14164             : 
   14165             :             // Default Constructor
   14166           8 :             rectangularwindow() : Vertex(4)
   14167             :             {
   14168           8 :             }
   14169             :         };
   14170             : 
   14171             :         // Object Data
   14172           8 :         Vector TVect;
   14173           8 :         rectangularwindow OriginalCoord;
   14174             : 
   14175           8 :         IConst = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
   14176             : 
   14177             :         // Height and width of original window
   14178           8 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
   14179           8 :         W = VecLength(TVect); // SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
   14180           8 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
   14181           8 :         H = VecLength(TVect); // SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)
   14182             : 
   14183             :         // Save coordinates of original window in case Window 5 data overwrites.
   14184          16 :         OriginalCoord.Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides}) =
   14185          24 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides});
   14186             : 
   14187             :         // Height and width of first glazing system
   14188           8 :         h1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysHeight;
   14189           8 :         w1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysWidth;
   14190             : 
   14191           8 :         Const2Name = state.dataConstruction->Construct(IConst).Name + ":2";
   14192           8 :         IConst2 = Util::FindItemInList(Const2Name, state.dataConstruction->Construct);
   14193             : 
   14194           8 :         if (IConst2 == 0) { // Only one glazing system on Window5 Data File for this window.
   14195             : 
   14196             :             // So... original dimensions and area of window are used (entered in IDF)
   14197             :             // Warning if dimensions of original window differ from those on Data File by more than 10%
   14198             : 
   14199           8 :             if (std::abs((H - h1) / H) > 0.10 || std::abs((W - w1) / W) > 0.10) {
   14200             : 
   14201           8 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   14202           0 :                     ShowWarningError(state,
   14203           0 :                                      format("SurfaceGeometry: ModifyWindow: Window {} uses the Window5 Data File Construction {}",
   14204           0 :                                             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
   14205           0 :                                             state.dataConstruction->Construct(IConst).Name));
   14206           0 :                     ShowContinueError(state, format("The height {:.3R}(m) or width  (m) of this window differs by more than 10%{:.3R}", H, W));
   14207           0 :                     ShowContinueError(state,
   14208           0 :                                       format("from the corresponding height {:.3R} (m) or width  (m) on the Window5 Data file.{:.3R}", h1, w1));
   14209           0 :                     ShowContinueError(state, "This will affect the frame heat transfer calculation if the frame in the Data File entry");
   14210           0 :                     ShowContinueError(state, "is not uniform, i.e., has sections with different geometry and/or thermal properties.");
   14211             :                 } else {
   14212           8 :                     ++state.dataSurfaceGeometry->Warning1Count;
   14213             :                 }
   14214             :             }
   14215             : 
   14216             :             // Calculate net area for base surface
   14217           8 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -=
   14218           8 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
   14219           8 :             if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
   14220           0 :                 ShowSevereError(state,
   14221           0 :                                 format("Subsurfaces have too much area for base surface={}",
   14222           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name));
   14223           0 :                 ShowContinueError(state, format("Subsurface creating error={}", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
   14224           0 :                 ErrorsFound = true;
   14225             :             }
   14226             : 
   14227             :             // Net area of base surface with unity window multipliers (used in shadowing checks)
   14228           8 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
   14229           8 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
   14230             : 
   14231             :         } else { // Two glazing systems on Window5 data file for this window
   14232             : 
   14233             :             // if exterior window, okay.
   14234             : 
   14235           0 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
   14236             :                 // There are two glazing systems (separated by a vertical or horizontal mullion) on the Window5 Data File.
   14237             :                 // Fill in geometry data for the second window (corresponding to the second glazing system on the data file.
   14238             :                 // The first glazing system is assumed to be at left for vertical mullion, at bottom for horizontal mullion.
   14239             :                 // The second glazing system is assumed to be at right for vertical mullion, at top for horizontal mullion.
   14240             :                 // The lower left-hand corner of the original window (its vertex #2) is assumed to coincide with
   14241             :                 // vertex #2 of the first glazing system.
   14242             : 
   14243           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   14244           0 :                     ShowMessage(state,
   14245           0 :                                 format("SurfaceGeometry: ModifyWindow: Window {} has been replaced with the Window 5/6 two glazing system=\"{}\".",
   14246           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
   14247           0 :                                        state.dataConstruction->Construct(IConst).Name));
   14248           0 :                     ShowContinueError(state, "Note that originally entered dimensions are overridden.");
   14249             :                 } else {
   14250           0 :                     ++state.dataSurfaceGeometry->Warning2Count;
   14251             :                 }
   14252             : 
   14253             :                 // Allocate another window
   14254           0 :                 AddWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
   14255             : 
   14256           0 :             } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond > 0) { // Interior window, specified  ! not external environment
   14257             : 
   14258           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   14259           0 :                     ShowWarningError(
   14260             :                         state,
   14261           0 :                         format("SurfaceGeometry: ModifyWindow: Interior Window {} has been replaced with the Window 5/6 two glazing system=\"{}\".",
   14262           0 :                                state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
   14263           0 :                                state.dataConstruction->Construct(IConst).Name));
   14264           0 :                     ShowContinueError(
   14265             :                         state, "Please check to make sure interior window is correct. Note that originally entered dimensions are overridden.");
   14266             :                 } else {
   14267           0 :                     ++state.dataSurfaceGeometry->Warning3Count;
   14268             :                 }
   14269             : 
   14270           0 :                 AddWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
   14271             : 
   14272             :             } else { // Interior window, specified not entered
   14273             : 
   14274           0 :                 ShowSevereError(state,
   14275           0 :                                 format("SurfaceGeometry: ModifyWindow: Interior Window {} is a window in an adjacent zone.",
   14276           0 :                                        state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
   14277           0 :                 ShowContinueError(
   14278             :                     state,
   14279           0 :                     format("Attempted to add/reverse Window 5/6 multiple glazing system=\"{}\".", state.dataConstruction->Construct(IConst).Name));
   14280           0 :                 ShowContinueError(state, "Cannot use these Window 5/6 constructs for these Interior Windows. Program will terminate.");
   14281           0 :                 ErrorsFound = true;
   14282             :             }
   14283             : 
   14284             :         } // End of check if one or two glazing systems are on the Window5 Data File
   14285           8 :     }
   14286             : 
   14287           0 :     void AddWindow(EnergyPlusData &state,
   14288             :                    int const SurfNum,    // SurfNum has construction of glazing system from Window5 Data File;
   14289             :                    bool &ErrorsFound,    // Set to true if errors found
   14290             :                    int &AddedSubSurfaces // Subsurfaces added when window references a
   14291             :     )
   14292             :     {
   14293             :         // SUBROUTINE INFORMATION:
   14294             :         //       AUTHOR         Linda Lawrie
   14295             :         //       DATE WRITTEN   Nov 2008
   14296             :         //       MODIFIED       na
   14297             :         //       RE-ENGINEERED  na
   14298             : 
   14299             :         // PURPOSE OF THIS SUBROUTINE:
   14300             :         // This routine is called from ModifyWindow to add a window.  Allows it to be
   14301             :         // called in more than one place in the calling routine so as to be able to have
   14302             :         // specific warnings or errors issued.
   14303             : 
   14304             :         // Using/Aliasing
   14305             : 
   14306             :         using namespace Vectors;
   14307             : 
   14308             :         // Locals
   14309             :         // SUBROUTINE ARGUMENT DEFINITIONS:
   14310             :         // If there is a second glazing systme on the Data File, SurfNum+1
   14311             :         // has the construction of the second glazing system.
   14312             : 
   14313             :         // 2-glazing system Window5 data file entry
   14314             : 
   14315             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   14316             :         int loop; // DO loop index
   14317             :         Real64 H; // Height and width of original window (m)
   14318             :         Real64 W;
   14319             :         Real64 MulWidth; // Mullion width (m)
   14320             :         Real64 h1;       // height and width of first glazing system (m)
   14321             :         Real64 w1;
   14322             :         Real64 h2; // height and width of second glazing system (m)
   14323             :         Real64 w2;
   14324             :         Real64 xa; // Vertex intermediate variables (m)
   14325             :         Real64 ya;
   14326             :         Real64 za;
   14327             :         Real64 xb;
   14328             :         Real64 yb;
   14329             :         Real64 zb;
   14330             :         Real64 dx; // Vertex displacements from original window (m)
   14331             :         Real64 dy;
   14332             :         int IConst;             // Construction number of first glazing system
   14333             :         int IConst2;            // Construction number of second glazing system
   14334           0 :         std::string Const2Name; // Name of construction of second glazing system
   14335             :         Real64 AreaNew;         // Sum of areas of the two glazing systems (m2)
   14336             : 
   14337             :         struct rectangularwindow
   14338             :         {
   14339             :             // Members
   14340             :             Array1D<Vector> Vertex;
   14341             : 
   14342             :             // Default Constructor
   14343           0 :             rectangularwindow() : Vertex(4)
   14344             :             {
   14345           0 :             }
   14346             :         };
   14347             : 
   14348             :         // Object Data
   14349           0 :         Vector TVect;
   14350           0 :         rectangularwindow NewCoord;
   14351           0 :         rectangularwindow OriginalCoord;
   14352             : 
   14353           0 :         IConst = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
   14354             : 
   14355             :         // Height and width of original window
   14356           0 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
   14357           0 :         W = VecLength(TVect); // SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
   14358           0 :         TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
   14359           0 :         H = VecLength(TVect); // SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)
   14360             : 
   14361             :         // Save coordinates of original window in case Window 5 data overwrites.
   14362           0 :         OriginalCoord.Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides}) =
   14363           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides});
   14364             : 
   14365             :         // Height and width of first glazing system
   14366           0 :         h1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysHeight;
   14367           0 :         w1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysWidth;
   14368             : 
   14369           0 :         Const2Name = state.dataConstruction->Construct(IConst).Name + ":2";
   14370           0 :         IConst2 = Util::FindItemInList(Const2Name, state.dataConstruction->Construct);
   14371             : 
   14372           0 :         ++AddedSubSurfaces;
   14373           0 :         state.dataSurfaceGeometry->SurfaceTmp.redimension(++state.dataSurface->TotSurfaces);
   14374             : 
   14375           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex.allocate(4);
   14376             : 
   14377           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + ":2";
   14378           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Construction = IConst2;
   14379           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ConstructionStoredInputValue = IConst2;
   14380           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Class = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class;
   14381           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
   14382             :         // Sine and cosine of azimuth and tilt
   14383           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SinAzim = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim;
   14384           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).CosAzim = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim;
   14385           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SinTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt;
   14386           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).CosTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt;
   14387             :         // Outward normal unit vector (pointing away from room)
   14388           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Centroid = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Centroid;
   14389           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsx = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx;
   14390           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsy = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy;
   14391           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsz = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz;
   14392           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NewellAreaVector =
   14393           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector;
   14394           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec;
   14395           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Reveal = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Reveal;
   14396           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Shape = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Shape;
   14397           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
   14398           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Tilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
   14399           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).convOrientation =
   14400           0 :             Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
   14401           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).HeatTransSurf =
   14402           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf;
   14403           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).BaseSurfName =
   14404           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
   14405           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).BaseSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf;
   14406           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName;
   14407           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Zone = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
   14408           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtBoundCondName =
   14409           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName;
   14410           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtBoundCond =
   14411           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond;
   14412           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar;
   14413           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind;
   14414           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorGround =
   14415           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround;
   14416           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorSky =
   14417           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
   14418           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorGroundIR =
   14419           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR;
   14420           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorSkyIR =
   14421           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR;
   14422           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr;
   14423           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SchedShadowSurfIndex =
   14424           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex;
   14425           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).activeWindowShadingControl =
   14426           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl;
   14427           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).windowShadingControlList =
   14428           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
   14429           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).HasShadeControl =
   14430           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl;
   14431           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).activeShadedConstruction =
   14432           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
   14433           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).windowShadingControlList =
   14434           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
   14435           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).shadedStormWinConstructionList =
   14436           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList;
   14437           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).FrameDivider =
   14438           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider;
   14439           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Multiplier = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
   14440           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NetAreaShadowCalc =
   14441           0 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc;
   14442             : 
   14443           0 :         MulWidth = state.dataConstruction->Construct(IConst).W5FileMullionWidth;
   14444           0 :         w2 = state.dataConstruction->Construct(IConst2).W5FileGlazingSysWidth;
   14445           0 :         h2 = state.dataConstruction->Construct(IConst2).W5FileGlazingSysHeight;
   14446             : 
   14447             :         // Correction to net area of base surface. Add back in the original glazing area and subtract the
   14448             :         // area of the two glazing systems. Note that for Surface(SurfNum)%Class = 'Window' the effect
   14449             :         // of a window multiplier is included in the glazing area. Note that frame areas are subtracted later.
   14450             : 
   14451           0 :         AreaNew = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier * (h1 * w1 + h2 * w2); // both glazing systems
   14452             :         // Adjust net area for base surface
   14453           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -= AreaNew;
   14454             : 
   14455             :         // Net area of base surface with unity window multipliers (used in shadowing checks)
   14456           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
   14457           0 :             AreaNew / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
   14458             : 
   14459             :         // Reset area, etc. of original window
   14460           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier * (h1 * w1);
   14461           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
   14462           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = h1 * w1;
   14463           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = 2 * (h1 + w1);
   14464           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = h1;
   14465           0 :         state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = w1;
   14466             :         // Set area, etc. of new window
   14467           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Area =
   14468           0 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Multiplier * (h2 * w2);
   14469           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).GrossArea =
   14470           0 :             state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Area;
   14471           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NetAreaShadowCalc = h2 * w2;
   14472           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Perimeter = 2 * (h2 + w2);
   14473           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Height = h2;
   14474           0 :         state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Width = w2;
   14475             : 
   14476           0 :         if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
   14477           0 :             ShowSevereError(state,
   14478           0 :                             format("SurfaceGeometry: ModifyWindow: Subsurfaces have too much area for base surface={}",
   14479           0 :                                    state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name));
   14480           0 :             ShowContinueError(state, format("Subsurface (window) creating error={}", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name));
   14481           0 :             ShowContinueError(state,
   14482           0 :                               format("This window has been replaced by two windows from the Window5 Data File of total area {:.2R} m2", AreaNew));
   14483           0 :             ErrorsFound = true;
   14484             :         }
   14485             : 
   14486             :         // Assign vertices to the new window; modify vertices of original window.
   14487             :         // In the following, vertices are numbered counter-clockwise with vertex #1 at the upper left.
   14488             : 
   14489           0 :         if (state.dataConstruction->Construct(IConst).W5FileMullionOrientation == DataWindowEquivalentLayer::Orientation::Vertical) {
   14490             : 
   14491             :             // VERTICAL MULLION: original window is modified to become left-hand glazing (system #1);
   14492             :             // new window is created to become right-hand glazing (system #2)
   14493             : 
   14494             :             // Left-hand glazing
   14495             : 
   14496             :             // Vertex 1
   14497           0 :             dx = 0.0;
   14498           0 :             dy = H - h1;
   14499           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14500           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14501           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14502           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14503           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14504           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14505           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14506           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14507           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14508             : 
   14509             :             // Vertex 2
   14510           0 :             dx = 0.0;
   14511           0 :             dy = H;
   14512           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14513           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14514           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14515           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14516           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14517           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14518           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14519           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14520           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14521             : 
   14522             :             // Vertex 3
   14523           0 :             dx = w1;
   14524           0 :             dy = H;
   14525           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14526           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14527           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14528           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14529           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14530           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14531           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14532           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14533           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14534             : 
   14535             :             // Vertex 4
   14536           0 :             dx = w1;
   14537           0 :             dy = H - h1;
   14538           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14539           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14540           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14541           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14542           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14543           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14544           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14545           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14546           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14547             : 
   14548           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++loop) {
   14549           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(loop) = NewCoord.Vertex(loop);
   14550             :             }
   14551             : 
   14552             :             // Right-hand glazing
   14553             : 
   14554             :             // Vertex 1
   14555           0 :             dx = w1 + MulWidth;
   14556           0 :             dy = H - (h1 + h2) / 2.0;
   14557           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14558           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14559           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14560           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14561           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14562           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14563           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14564           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14565           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14566             : 
   14567             :             // Vertex 2
   14568           0 :             dx = w1 + MulWidth;
   14569           0 :             dy = H + (h2 - h1) / 2.0;
   14570           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14571           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14572           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14573           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14574           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14575           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14576           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14577           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14578           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14579             : 
   14580             :             // Vertex 3
   14581           0 :             dx = w1 + MulWidth + w2;
   14582           0 :             dy = H + (h2 - h1) / 2.0;
   14583           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14584           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14585           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14586           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14587           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14588           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14589           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14590           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14591           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14592             : 
   14593             :             // Vertex 4
   14594           0 :             dx = w1 + MulWidth + w2;
   14595           0 :             dy = H - (h1 + h2) / 2.0;
   14596           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14597           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14598           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14599           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14600           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14601           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14602           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14603           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14604           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14605             : 
   14606           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides; ++loop) {
   14607           0 :                 state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex(loop) = NewCoord.Vertex(loop);
   14608             :             }
   14609             : 
   14610             :         } else { // Horizontal mullion
   14611             : 
   14612             :             // HORIZONTAL MULLION: original window is modified to become bottom glazing (system #1);
   14613             :             // new window is created to become top glazing (system #2)
   14614             : 
   14615             :             // Bottom glazing
   14616             : 
   14617             :             // Vertex 1
   14618           0 :             dx = 0.0;
   14619           0 :             dy = H - h1;
   14620           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14621           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14622           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14623           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14624           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14625           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14626           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14627           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14628           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14629             : 
   14630             :             // Vertex 2
   14631           0 :             dx = 0.0;
   14632           0 :             dy = H;
   14633           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14634           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14635           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14636           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14637           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14638           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14639           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14640           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14641           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14642             : 
   14643             :             // Vertex 3
   14644           0 :             dx = w1;
   14645           0 :             dy = H;
   14646           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14647           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14648           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14649           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14650           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14651           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14652           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14653           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14654           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14655             : 
   14656             :             // Vertex 4
   14657           0 :             dx = w1;
   14658           0 :             dy = H - h1;
   14659           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14660           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14661           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14662           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14663           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14664           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14665           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14666           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14667           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14668             : 
   14669           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++loop) {
   14670           0 :                 state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(loop) = NewCoord.Vertex(loop);
   14671             :             }
   14672             : 
   14673             :             // Top glazing
   14674             : 
   14675             :             // Vertex 1
   14676           0 :             dx = (w1 - w2) / 2.0;
   14677           0 :             dy = H - (h1 + h2 + MulWidth);
   14678           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14679           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14680           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14681           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14682           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14683           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14684           0 :             NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
   14685           0 :             NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
   14686           0 :             NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
   14687             : 
   14688             :             // Vertex 2
   14689           0 :             dx = (w1 - w2) / 2.0;
   14690           0 :             dy = H - (h1 + MulWidth);
   14691           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14692           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14693           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14694           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14695           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14696           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14697           0 :             NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
   14698           0 :             NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
   14699           0 :             NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
   14700             : 
   14701             :             // Vertex 3
   14702           0 :             dx = (w1 + w2) / 2.0;
   14703           0 :             dy = H - (h1 + MulWidth);
   14704           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14705           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14706           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14707           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14708           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14709           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14710           0 :             NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
   14711           0 :             NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
   14712           0 :             NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
   14713             : 
   14714             :             // Vertex 4
   14715           0 :             dx = (w1 + w2) / 2.0;
   14716           0 :             dy = H - (h1 + h2 + MulWidth);
   14717           0 :             xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
   14718           0 :             ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
   14719           0 :             za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
   14720           0 :             xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
   14721           0 :             yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
   14722           0 :             zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
   14723           0 :             NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
   14724           0 :             NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
   14725           0 :             NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
   14726             : 
   14727           0 :             for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides; ++loop) {
   14728           0 :                 state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex(loop) = NewCoord.Vertex(loop);
   14729             :             }
   14730             : 
   14731             :         } // End of check if vertical or horizontal mullion
   14732           0 :     }
   14733             : 
   14734       42458 :     void TransformVertsByAspect(EnergyPlusData &state,
   14735             :                                 int const SurfNum, // Current surface number
   14736             :                                 int const NSides   // Number of sides to figure
   14737             :     )
   14738             :     {
   14739             :         // SUBROUTINE INFORMATION:
   14740             :         //       AUTHOR         Brent T Griffith
   14741             :         //       DATE WRITTEN   April 2003
   14742             :         //       MODIFIED       na
   14743             :         //       RE-ENGINEERED  na
   14744             : 
   14745             :         // PURPOSE OF THIS SUBROUTINE:
   14746             :         // Alter input for surface geometry
   14747             :         // Optimizing building design for energy can involve
   14748             :         //  altering building geometry.  Rather than assemble routines to transform
   14749             :         //  geometry through pre-processing on input, it may be simpler to change
   14750             :         //  vertices within EnergyPlus since it already reads the data from the input
   14751             :         //  file and there would no longer be a need to rewrite the text data.
   14752             :         //  This is essentially a crude hack to allow adjusting geometry with
   14753             :         //  a single parameter...
   14754             : 
   14755             :         // METHODOLOGY EMPLOYED:
   14756             :         // once vertices have been converted to WCS, change them to reflect a different aspect
   14757             :         // ratio for the entire building based on user input.
   14758             :         // This routine is called once for each surface by subroutine GetVertices
   14759             : 
   14760       42458 :         static std::string const CurrentModuleObject("GeometryTransform");
   14761             : 
   14762       42458 :         Array1D_string cAlphas(1);
   14763       42458 :         Array1D<Real64> rNumerics(2);
   14764             :         int NAlphas;
   14765             :         int NNum;
   14766             :         int IOStat;
   14767       42458 :         auto &OldAspectRatio = state.dataSurfaceGeometry->OldAspectRatio;
   14768       42458 :         auto &NewAspectRatio = state.dataSurfaceGeometry->NewAspectRatio;
   14769       42458 :         auto &transformPlane = state.dataSurfaceGeometry->transformPlane;
   14770             :         int n;
   14771             :         Real64 Xo;
   14772             :         Real64 XnoRot;
   14773             :         Real64 Xtrans;
   14774             :         Real64 Yo;
   14775             :         Real64 YnoRot;
   14776             :         Real64 Ytrans;
   14777             :         // begin execution
   14778             :         // get user input...
   14779             : 
   14780       42458 :         if (state.dataSurfaceGeometry->firstTime) {
   14781         765 :             if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject) == 1) {
   14782           2 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   14783             :                                                                          CurrentModuleObject,
   14784             :                                                                          1,
   14785             :                                                                          cAlphas,
   14786             :                                                                          NAlphas,
   14787             :                                                                          rNumerics,
   14788             :                                                                          NNum,
   14789             :                                                                          IOStat,
   14790           1 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
   14791           1 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
   14792           1 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
   14793           1 :                                                                          state.dataIPShortCut->cNumericFieldNames);
   14794           1 :                 OldAspectRatio = rNumerics(1);
   14795           1 :                 NewAspectRatio = rNumerics(2);
   14796           1 :                 transformPlane = cAlphas(1);
   14797           1 :                 if (transformPlane != "XY") {
   14798           0 :                     ShowWarningError(
   14799           0 :                         state, format("{}: invalid {}=\"{}...ignored.", CurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(1), cAlphas(1)));
   14800             :                 }
   14801           1 :                 state.dataSurfaceGeometry->firstTime = false;
   14802           1 :                 state.dataSurfaceGeometry->noTransform = false;
   14803           1 :                 state.dataSurface->AspectTransform = true;
   14804           1 :                 if (state.dataSurface->WorldCoordSystem) {
   14805           0 :                     ShowWarningError(state, format("{}: must use Relative Coordinate System.  Transform request ignored.", CurrentModuleObject));
   14806           0 :                     state.dataSurfaceGeometry->noTransform = true;
   14807           0 :                     state.dataSurface->AspectTransform = false;
   14808             :                 }
   14809             :             } else {
   14810         764 :                 state.dataSurfaceGeometry->firstTime = false;
   14811             :             }
   14812             :         }
   14813       42458 :         if (state.dataSurfaceGeometry->noTransform) return;
   14814             : 
   14815             :         // check surface type.
   14816          48 :         if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) {
   14817             :             // Site Shading do not get transformed.
   14818           2 :             if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_F) return;
   14819             :         }
   14820             : 
   14821             :         // testing method of transforming  x and y coordinates as follows
   14822             : 
   14823             :         // this works if not rotated wrt north axis ... but if it is, then trouble
   14824             :         // try to first derotate it , transform by aspect and then rotate back.
   14825             : 
   14826         240 :         for (n = 1; n <= NSides; ++n) {
   14827         192 :             Xo = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x; // world coordinates.... shifted by relative north angle...
   14828         192 :             Yo = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
   14829             :             // next derotate the building
   14830         192 :             XnoRot = Xo * state.dataSurfaceGeometry->CosBldgRelNorth + Yo * state.dataSurfaceGeometry->SinBldgRelNorth;
   14831         192 :             YnoRot = Yo * state.dataSurfaceGeometry->CosBldgRelNorth - Xo * state.dataSurfaceGeometry->SinBldgRelNorth;
   14832             :             // translate
   14833         192 :             Xtrans = XnoRot * std::sqrt(NewAspectRatio / OldAspectRatio);
   14834         192 :             Ytrans = YnoRot * std::sqrt(OldAspectRatio / NewAspectRatio);
   14835             :             // rerotate
   14836         192 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
   14837         192 :                 Xtrans * state.dataSurfaceGeometry->CosBldgRelNorth - Ytrans * state.dataSurfaceGeometry->SinBldgRelNorth;
   14838             : 
   14839         192 :             state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
   14840         192 :                 Xtrans * state.dataSurfaceGeometry->SinBldgRelNorth + Ytrans * state.dataSurfaceGeometry->CosBldgRelNorth;
   14841             :         }
   14842       84868 :     }
   14843             : 
   14844         796 :     void CalcSurfaceCentroid(EnergyPlusData &state)
   14845             :     {
   14846             :         // SUBROUTINE INFORMATION:
   14847             :         //       AUTHOR         B. Griffith
   14848             :         //       DATE WRITTEN   Feb. 2004
   14849             :         //       MODIFIED       na
   14850             :         //       RE-ENGINEERED  na
   14851             : 
   14852             :         // PURPOSE OF THIS SUBROUTINE:
   14853             :         // compute centroid of all the surfaces in the main
   14854             :         // surface structure. Store the vertex coordinates of
   14855             :         // the centroid in the 'SURFACE' derived type.
   14856             : 
   14857             :         // METHODOLOGY EMPLOYED:
   14858             :         // The centroid of triangle is easily computed by averaging the vertices
   14859             :         // The centroid of a quadrilateral is computed by area weighting the centroids
   14860             :         // of two triangles.
   14861             :         // (Algorithm would need to be changed for higher order
   14862             :         // polygons with more than four sides).
   14863             : 
   14864             :         using namespace Vectors;
   14865             : 
   14866         796 :         auto &Triangle1 = state.dataSurfaceGeometry->Triangle1;
   14867         796 :         auto &Triangle2 = state.dataSurfaceGeometry->Triangle2;
   14868         796 :         static Vector const zero_vector(0.0);
   14869         796 :         Vector centroid;
   14870             : 
   14871         796 :         int negZcount(0); // for warning error in surface centroids
   14872             : 
   14873             :         // loop through all the surfaces
   14874       46840 :         for (int ThisSurf = 1; ThisSurf <= state.dataSurface->TotSurfaces; ++ThisSurf) {
   14875       46044 :             auto &surface = state.dataSurface->Surface(ThisSurf);
   14876             : 
   14877       46044 :             if (surface.Class == SurfaceClass::IntMass) continue;
   14878             : 
   14879       43646 :             auto const &vertex = surface.Vertex;
   14880             : 
   14881       43646 :             if (surface.Sides == 3) { // 3-sided polygon
   14882             : 
   14883         199 :                 centroid = cen(vertex(1), vertex(2), vertex(3));
   14884             : 
   14885       43447 :             } else if (surface.Sides == 4) { // 4-sided polygon
   14886             : 
   14887             :                 // split into 2 3-sided polygons (Triangle 1 and Triangle 2)
   14888       43250 :                 Triangle1(1) = vertex(1);
   14889       43250 :                 Triangle1(2) = vertex(2);
   14890       43250 :                 Triangle1(3) = vertex(3);
   14891       43250 :                 Triangle2(1) = vertex(1);
   14892       43250 :                 Triangle2(2) = vertex(3);
   14893       43250 :                 Triangle2(3) = vertex(4);
   14894             : 
   14895             :                 // get total Area of quad.
   14896       43250 :                 Real64 TotalArea(surface.GrossArea);
   14897       43250 :                 if (TotalArea <= 0.0) {
   14898             :                     // catch a problem....
   14899           0 :                     ShowWarningError(state, format("CalcSurfaceCentroid: zero area surface, for surface={}", surface.Name));
   14900           0 :                     continue;
   14901             :                 }
   14902             : 
   14903             :                 // get area fraction of triangles.
   14904       43250 :                 Real64 Tri1Area(AreaPolygon(3, Triangle1) / TotalArea);
   14905       43250 :                 Real64 Tri2Area(AreaPolygon(3, Triangle2) / TotalArea);
   14906             : 
   14907             :                 // check if sum of fractions are slightly greater than 1.0 which is a symptom of the triangles for a non-convex
   14908             :                 // quadralateral using the wrong two triangles
   14909       43250 :                 if ((Tri1Area + Tri2Area) > 1.05) {
   14910             : 
   14911             :                     // if so repeat the process with the other two possible triangles (notice the vertices are in a different order this
   14912             :                     // time) split into 2 3-sided polygons (Triangle 1 and Triangle 2)
   14913          20 :                     Triangle1(1) = vertex(1);
   14914          20 :                     Triangle1(2) = vertex(2);
   14915          20 :                     Triangle1(3) = vertex(4);
   14916          20 :                     Triangle2(1) = vertex(2);
   14917          20 :                     Triangle2(2) = vertex(3);
   14918          20 :                     Triangle2(3) = vertex(4);
   14919             : 
   14920             :                     // get area fraction of triangles.
   14921          20 :                     Real64 AreaTriangle1 = AreaPolygon(3, Triangle1);
   14922          20 :                     Real64 AreaTriangle2 = AreaPolygon(3, Triangle2);
   14923          20 :                     TotalArea = AreaTriangle1 + AreaTriangle2;
   14924          20 :                     Tri1Area = AreaTriangle1 / TotalArea;
   14925          20 :                     Tri2Area = AreaTriangle2 / TotalArea;
   14926             :                 }
   14927             : 
   14928             :                 // get centroid of Triangle 1
   14929       43250 :                 Vector cen1(cen(Triangle1(1), Triangle1(2), Triangle1(3)));
   14930             : 
   14931             :                 // get centroid of Triangle 2
   14932       43250 :                 Vector cen2(cen(Triangle2(1), Triangle2(2), Triangle2(3)));
   14933             : 
   14934             :                 // find area weighted combination of the two centroids (coded to avoid temporary Vectors)
   14935       43250 :                 cen1 *= Tri1Area;
   14936       43250 :                 cen2 *= Tri2Area;
   14937       43250 :                 centroid = cen1;
   14938       43250 :                 centroid += cen2;
   14939             : 
   14940       43447 :             } else if (surface.Sides >= 5) { // multi-sided polygon
   14941             :                 // (Maybe triangulate?  For now, use old "z" average method")
   14942             :                 // and X and Y -- straight average
   14943             : 
   14944             :                 //        X1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%x)
   14945             :                 //        X2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%x)
   14946             :                 //        Y1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%y)
   14947             :                 //        Y2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%y)
   14948             :                 //        Z1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%z)
   14949             :                 //        Z2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%z)
   14950             :                 //        Xcm=(X1+X2)/2.0d0
   14951             :                 //        Ycm=(Y1+Y2)/2.0d0
   14952             :                 //        Zcm=(Z1+Z2)/2.0d0
   14953             : 
   14954             :                 // Calc centroid as average of surfaces
   14955         197 :                 centroid = 0.0;
   14956        2025 :                 for (int vert = 1; vert <= surface.Sides; ++vert) {
   14957        1828 :                     centroid += vertex(vert);
   14958             :                 }
   14959         197 :                 centroid /= double(surface.Sides);
   14960             : 
   14961             :             } else {
   14962             : 
   14963           0 :                 if (!surface.Name.empty()) {
   14964           0 :                     ShowWarningError(state, format("CalcSurfaceCentroid: caught problem with # of sides, for surface={}", surface.Name));
   14965           0 :                     ShowContinueError(state, format("... number of sides must be >= 3, this surface # sides={}", surface.Sides));
   14966             :                 } else {
   14967           0 :                     ShowWarningError(state, format("CalcSurfaceCentroid: caught problem with # of sides, for surface=#{}", ThisSurf));
   14968           0 :                     ShowContinueError(state,
   14969             :                                       "...surface name is blank. Examine surfaces -- this may be a problem with ill-formed interzone surfaces.");
   14970           0 :                     ShowContinueError(state, format("... number of sides must be >= 3, this surface # sides={}", surface.Sides));
   14971             :                 }
   14972           0 :                 centroid = 0.0;
   14973             :             }
   14974             : 
   14975             :             // store result in the surface structure in DataSurfaces
   14976       43646 :             surface.Centroid = centroid;
   14977             : 
   14978       43646 :             if (centroid.z < 0.0) {
   14979         303 :                 if (surface.ExtWind || surface.ExtBoundCond == ExternalEnvironment) ++negZcount;
   14980             :             }
   14981             : 
   14982             :         } // loop through surfaces
   14983             : 
   14984         796 :         if (negZcount > 0) {
   14985           4 :             ShowWarningError(state, format("CalcSurfaceCentroid: {} Surfaces have the Z coordinate < 0.", negZcount));
   14986           4 :             ShowContinueError(state, "...in any calculations, Wind Speed will be 0.0 for these surfaces.");
   14987           8 :             ShowContinueError(state,
   14988           8 :                               format("...in any calculations, Outside temperatures will be the outside temperature + {:.3R} for these surfaces.",
   14989           4 :                                      state.dataEnvrn->WeatherFileTempModCoeff));
   14990           4 :             ShowContinueError(state, "...that is, these surfaces will have conditions as though at ground level.");
   14991             :         }
   14992         796 :     }
   14993             : 
   14994         796 :     void SetupShadeSurfacesForSolarCalcs(EnergyPlusData &state)
   14995             :     {
   14996             :         // SUBROUTINE INFORMATION:
   14997             :         //       AUTHOR         B. Griffith
   14998             :         //       DATE WRITTEN   Dec. 2008
   14999             :         //       MODIFIED       na
   15000             :         //       RE-ENGINEERED  na
   15001             : 
   15002             :         // PURPOSE OF THIS SUBROUTINE:
   15003             :         // determine if Shading surfaces need full solar calcs because they
   15004             :         // are also used to define geometry of an active solar component.
   15005             :         // Normally, a shading surface is not included in calculations of incident solar, only shading
   15006             : 
   15007             :         // METHODOLOGY EMPLOYED:
   15008             :         // Mine solar renewables input and collect surface names.
   15009             :         // find shading surfaces with names that match those in solar objects.
   15010             :         // setup flags for shading surfaces so that the solar renewables can resuse incident solar calcs
   15011             :         // new solar component models that use shading surfaces will have to extend the code here.
   15012             : 
   15013             :         // Using/Aliasing
   15014             : 
   15015             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   15016         796 :         Array1D_string TmpCandidateSurfaceNames;
   15017         796 :         Array1D_string TmpCandidateICSSurfaceNames;
   15018         796 :         Array1D_string TmpCandidateICSBCTypeNames;
   15019             :         int NumCandidateNames;
   15020             :         int NumOfCollectors;
   15021             :         int NumOfICSUnits;
   15022             :         int NumOfFlatPlateUnits;
   15023             :         int NumPVTs;
   15024             :         int NumPVs;
   15025             :         int SurfNum;
   15026             :         int Found;
   15027             :         int CollectorNum;
   15028             :         int PVTnum;
   15029             :         int PVnum;
   15030             :         int NumAlphas;  // Number of alpha names being passed
   15031             :         int NumNumbers; // Number of numeric parameters being passed
   15032             :         int IOStatus;
   15033         796 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
   15034             :         // First collect names of surfaces referenced by active solar components
   15035         796 :         cCurrentModuleObject = "SolarCollector:FlatPlate:Water";
   15036         796 :         NumOfFlatPlateUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   15037         796 :         cCurrentModuleObject = "SolarCollector:FlatPlate:PhotovoltaicThermal";
   15038         796 :         NumPVTs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   15039         796 :         cCurrentModuleObject = "Generator:Photovoltaic";
   15040         796 :         NumPVs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   15041         796 :         cCurrentModuleObject = "SolarCollector:IntegralCollectorStorage";
   15042         796 :         NumOfICSUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
   15043             : 
   15044         796 :         NumCandidateNames = NumOfFlatPlateUnits + NumPVTs + NumPVs + NumOfICSUnits;
   15045         796 :         NumOfCollectors = NumOfFlatPlateUnits + NumOfICSUnits;
   15046             : 
   15047         796 :         TmpCandidateSurfaceNames.allocate(NumCandidateNames);
   15048         796 :         TmpCandidateICSSurfaceNames.allocate(NumOfCollectors);
   15049         796 :         TmpCandidateICSBCTypeNames.allocate(NumOfCollectors);
   15050             : 
   15051         796 :         if (NumOfCollectors > 0) {
   15052           3 :             cCurrentModuleObject = "SolarCollector:FlatPlate:Water";
   15053          11 :             for (CollectorNum = 1; CollectorNum <= NumOfFlatPlateUnits; ++CollectorNum) {
   15054             : 
   15055          16 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   15056             :                                                                          cCurrentModuleObject,
   15057             :                                                                          CollectorNum,
   15058           8 :                                                                          state.dataIPShortCut->cAlphaArgs,
   15059             :                                                                          NumAlphas,
   15060           8 :                                                                          state.dataIPShortCut->rNumericArgs,
   15061             :                                                                          NumNumbers,
   15062             :                                                                          IOStatus);
   15063             : 
   15064           8 :                 TmpCandidateSurfaceNames(CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
   15065           8 :                 TmpCandidateICSBCTypeNames(CollectorNum) = "";
   15066             :             }
   15067             :         }
   15068             : 
   15069         796 :         if (NumPVTs > 0) {
   15070           2 :             cCurrentModuleObject = "SolarCollector:FlatPlate:PhotovoltaicThermal";
   15071          22 :             for (PVTnum = 1; PVTnum <= NumPVTs; ++PVTnum) {
   15072             : 
   15073          40 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   15074             :                                                                          cCurrentModuleObject,
   15075             :                                                                          PVTnum,
   15076          20 :                                                                          state.dataIPShortCut->cAlphaArgs,
   15077             :                                                                          NumAlphas,
   15078          20 :                                                                          state.dataIPShortCut->rNumericArgs,
   15079             :                                                                          NumNumbers,
   15080             :                                                                          IOStatus);
   15081             : 
   15082          20 :                 TmpCandidateSurfaceNames(NumOfFlatPlateUnits + PVTnum) = state.dataIPShortCut->cAlphaArgs(2);
   15083             :             }
   15084             :         }
   15085             : 
   15086         796 :         if (NumPVs > 0) {
   15087           6 :             cCurrentModuleObject = "Generator:Photovoltaic";
   15088          59 :             for (PVnum = 1; PVnum <= NumPVs; ++PVnum) {
   15089         106 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   15090             :                                                                          cCurrentModuleObject,
   15091             :                                                                          PVnum,
   15092          53 :                                                                          state.dataIPShortCut->cAlphaArgs,
   15093             :                                                                          NumAlphas,
   15094          53 :                                                                          state.dataIPShortCut->rNumericArgs,
   15095             :                                                                          NumNumbers,
   15096             :                                                                          IOStatus);
   15097          53 :                 TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + PVnum) = state.dataIPShortCut->cAlphaArgs(2);
   15098             :             }
   15099             :         }
   15100             : 
   15101         796 :         if (NumOfICSUnits > 0) {
   15102           1 :             cCurrentModuleObject = "SolarCollector:IntegralCollectorStorage";
   15103           3 :             for (CollectorNum = 1; CollectorNum <= NumOfICSUnits; ++CollectorNum) {
   15104           4 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
   15105             :                                                                          cCurrentModuleObject,
   15106             :                                                                          CollectorNum,
   15107           2 :                                                                          state.dataIPShortCut->cAlphaArgs,
   15108             :                                                                          NumAlphas,
   15109           2 :                                                                          state.dataIPShortCut->rNumericArgs,
   15110             :                                                                          NumNumbers,
   15111             :                                                                          IOStatus);
   15112           2 :                 TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + NumPVs + CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
   15113           2 :                 TmpCandidateICSSurfaceNames(NumOfFlatPlateUnits + CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
   15114           2 :                 TmpCandidateICSBCTypeNames(NumOfFlatPlateUnits + CollectorNum) = state.dataIPShortCut->cAlphaArgs(4);
   15115             :             }
   15116             :         }
   15117             : 
   15118             :         // loop through all the surfaces
   15119       46840 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
   15120       46044 :             auto &surf = state.dataSurface->Surface(SurfNum);
   15121       46044 :             Found = Util::FindItemInList(surf.Name, TmpCandidateSurfaceNames, NumCandidateNames);
   15122       46044 :             if (Found > 0) {
   15123          53 :                 if (!surf.HeatTransSurf) { // not BIPV, must be a shading surf with solar device
   15124             :                     // Setup missing values to allow shading surfaces to model incident solar and wind
   15125          21 :                     surf.ExtSolar = true;
   15126          21 :                     surf.ExtWind = true;
   15127          21 :                     surf.ViewFactorGround = 0.5 * (1.0 - surf.CosTilt);
   15128             :                 }
   15129             :                 // check if this surface is used for ICS collector mounting and has OthersideCondictionsModel as its
   15130             :                 // boundary condition
   15131          53 :                 if (NumOfICSUnits > 0) {
   15132           6 :                     for (CollectorNum = 1; CollectorNum <= NumOfCollectors; ++CollectorNum) {
   15133           6 :                         if (Util::SameString(surf.Name, TmpCandidateICSSurfaceNames(CollectorNum)) &&
   15134           6 :                             Util::SameString(TmpCandidateICSBCTypeNames(CollectorNum), "OTHERSIDECONDITIONSMODEL")) {
   15135           2 :                             state.dataSurface->SurfIsICS(SurfNum) = true;
   15136           2 :                             state.dataSurface->SurfICSPtr(SurfNum) = CollectorNum;
   15137             :                         }
   15138             :                     }
   15139             :                 }
   15140             : 
   15141             :             } // end of IF (Found > 0) Then
   15142             :         }
   15143         796 :     }
   15144             : 
   15145             :     void
   15146        1592 :     SetupEnclosuresAndAirBoundaries(EnergyPlusData &state,
   15147             :                                     EPVector<DataViewFactorInformation::EnclosureViewFactorInformation> &Enclosures, // Radiant or Solar Enclosures
   15148             :                                     SurfaceGeometry::enclosureType const EnclosureType,                              // Radiant or Solar
   15149             :                                     bool &ErrorsFound)                                                               // Set to true if errors found
   15150             :     {
   15151             :         static constexpr std::string_view RoutineName = "SetupEnclosuresAndAirBoundaries";
   15152        1592 :         bool anyGroupedSpaces = false;
   15153        1592 :         bool radiantSetup = false;
   15154        1592 :         bool solarSetup = false;
   15155        1592 :         std::string RadiantOrSolar = "";
   15156        1592 :         int enclosureNum = 0;
   15157        1592 :         if (EnclosureType == RadiantEnclosures) {
   15158         796 :             radiantSetup = true;
   15159         796 :             RadiantOrSolar = "Radiant";
   15160         796 :             state.dataViewFactor->EnclRadInfo.allocate(state.dataGlobal->numSpaces);
   15161         796 :         } else if (EnclosureType == SolarEnclosures) {
   15162         796 :             solarSetup = true;
   15163         796 :             RadiantOrSolar = "Solar";
   15164         796 :             state.dataViewFactor->EnclSolInfo.allocate(state.dataGlobal->numSpaces);
   15165             :         } else {
   15166           0 :             ShowFatalError(
   15167           0 :                 state, format("{}: Illegal call to this function. Second argument must be 'RadiantEnclosures' or 'SolarEnclosures'", RoutineName));
   15168             :         }
   15169        1592 :         if (std::any_of(state.dataConstruction->Construct.begin(),
   15170        1592 :                         state.dataConstruction->Construct.end(),
   15171       12055 :                         [](Construction::ConstructionProps const &e) { return e.TypeIsAirBoundary; })) {
   15172          10 :             int errorCount = 0;
   15173         632 :             for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
   15174         622 :                 auto &surf = state.dataSurface->Surface(surfNum);
   15175         622 :                 if (surf.Construction == 0) continue;
   15176         582 :                 auto &constr = state.dataConstruction->Construct(surf.Construction);
   15177         582 :                 if (!constr.TypeIsAirBoundary) continue;
   15178          36 :                 surf.IsAirBoundarySurf = true;
   15179             : 
   15180             :                 // Check for invalid air boundary surfaces - valid only on non-adiabatic interzone surfaces
   15181             :                 // Only check this once during radiant setup, skip for solar setup
   15182          36 :                 if (radiantSetup && (surf.ExtBoundCond <= 0 || surf.ExtBoundCond == surfNum)) {
   15183           0 :                     ErrorsFound = true;
   15184           0 :                     if (!state.dataGlobal->DisplayExtraWarnings) {
   15185           0 :                         ++errorCount;
   15186             :                     } else {
   15187           0 :                         ShowSevereError(
   15188           0 :                             state, format("{}: Surface=\"{}\" uses Construction:AirBoundary in a non-interzone surface.", RoutineName, surf.Name));
   15189             :                     }
   15190             :                 } else {
   15191             :                     // Process air boundary - set surface properties and set up enclosures
   15192             :                     // Radiant exchange
   15193          36 :                     if (surf.IsAirBoundarySurf) {
   15194             :                         // Boundary is grouped - assign enclosure
   15195          36 :                         state.dataHeatBal->AnyAirBoundary = true;
   15196          36 :                         int thisSideEnclosureNum = 0;
   15197          36 :                         int otherSideEnclosureNum = 0;
   15198          36 :                         if (radiantSetup) {
   15199             :                             // Radiant enclosure setup
   15200          18 :                             constr.IsUsedCTF = false;
   15201          18 :                             surf.HeatTransSurf = false;
   15202          18 :                             surf.HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::AirBoundaryNoHT;
   15203          18 :                             thisSideEnclosureNum = state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum;
   15204          18 :                             otherSideEnclosureNum =
   15205          18 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum;
   15206             :                         } else {
   15207             :                             // Solar enclosure setup
   15208          18 :                             thisSideEnclosureNum = state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum;
   15209          18 :                             otherSideEnclosureNum =
   15210          18 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum;
   15211             :                         }
   15212          36 :                         anyGroupedSpaces = true;
   15213          36 :                         if ((thisSideEnclosureNum == 0) && (otherSideEnclosureNum == 0)) {
   15214             :                             // Neither zone is assigned to an enclosure, so increment the counter and assign to both
   15215          10 :                             ++enclosureNum;
   15216          10 :                             auto &thisEnclosure = Enclosures(enclosureNum);
   15217          10 :                             thisSideEnclosureNum = enclosureNum;
   15218          10 :                             thisEnclosure.Name = format("{} Enclosure {}", RadiantOrSolar, enclosureNum);
   15219          10 :                             thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(surf.spaceNum).Name);
   15220          10 :                             thisEnclosure.spaceNums.push_back(surf.spaceNum);
   15221          10 :                             thisEnclosure.FloorArea += state.dataHeatBal->space(surf.spaceNum).FloorArea;
   15222          10 :                             otherSideEnclosureNum = enclosureNum;
   15223          10 :                             int otherSideSpaceNum = state.dataSurface->Surface(surf.ExtBoundCond).spaceNum;
   15224          10 :                             if (otherSideSpaceNum != surf.spaceNum) {
   15225          10 :                                 thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(otherSideSpaceNum).Name);
   15226          10 :                                 thisEnclosure.spaceNums.push_back(otherSideSpaceNum);
   15227          10 :                                 thisEnclosure.FloorArea += state.dataHeatBal->space(otherSideSpaceNum).FloorArea;
   15228             :                             }
   15229          10 :                             if (radiantSetup) {
   15230           5 :                                 state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum = thisSideEnclosureNum;
   15231           5 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum =
   15232             :                                     otherSideEnclosureNum;
   15233             :                             } else {
   15234           5 :                                 thisEnclosure.ExtWindowArea += state.dataHeatBal->space(surf.spaceNum).extWindowArea;
   15235           5 :                                 thisEnclosure.TotalSurfArea += state.dataHeatBal->space(surf.spaceNum).totalSurfArea;
   15236           5 :                                 if (otherSideSpaceNum != surf.spaceNum) {
   15237           5 :                                     thisEnclosure.ExtWindowArea += state.dataHeatBal->space(otherSideSpaceNum).extWindowArea;
   15238           5 :                                     thisEnclosure.TotalSurfArea += state.dataHeatBal->space(otherSideSpaceNum).totalSurfArea;
   15239             :                                 }
   15240           5 :                                 state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum = thisSideEnclosureNum;
   15241           5 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum =
   15242             :                                     otherSideEnclosureNum;
   15243             :                             }
   15244          36 :                         } else if (thisSideEnclosureNum == 0) {
   15245             :                             // Other side is assigned, so use that one for both
   15246           0 :                             thisSideEnclosureNum = otherSideEnclosureNum;
   15247           0 :                             auto &thisEnclosure = Enclosures(thisSideEnclosureNum);
   15248           0 :                             thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(surf.spaceNum).Name);
   15249           0 :                             thisEnclosure.spaceNums.push_back(surf.spaceNum);
   15250           0 :                             thisEnclosure.FloorArea += state.dataHeatBal->space(surf.spaceNum).FloorArea;
   15251           0 :                             if (radiantSetup) {
   15252           0 :                                 state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum = thisSideEnclosureNum;
   15253             :                             } else {
   15254           0 :                                 thisEnclosure.ExtWindowArea += state.dataHeatBal->space(surf.spaceNum).extWindowArea;
   15255           0 :                                 thisEnclosure.TotalSurfArea += state.dataHeatBal->space(surf.spaceNum).totalSurfArea;
   15256           0 :                                 state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum = thisSideEnclosureNum;
   15257             :                             }
   15258          26 :                         } else if (otherSideEnclosureNum == 0) {
   15259             :                             // This side is assigned, so use that one for both
   15260           4 :                             otherSideEnclosureNum = thisSideEnclosureNum;
   15261           4 :                             auto &thisEnclosure = Enclosures(thisSideEnclosureNum);
   15262           4 :                             thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).Name);
   15263           4 :                             thisEnclosure.spaceNums.push_back(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
   15264           4 :                             thisEnclosure.FloorArea += state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).FloorArea;
   15265           4 :                             if (radiantSetup) {
   15266           2 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum =
   15267             :                                     otherSideEnclosureNum;
   15268             :                             } else {
   15269           2 :                                 thisEnclosure.ExtWindowArea +=
   15270           2 :                                     state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).extWindowArea;
   15271           2 :                                 thisEnclosure.TotalSurfArea +=
   15272           2 :                                     state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).totalSurfArea;
   15273           2 :                                 state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum =
   15274             :                                     otherSideEnclosureNum;
   15275             :                             }
   15276          22 :                         } else if (thisSideEnclosureNum != otherSideEnclosureNum) {
   15277             :                             // If both sides are already assigned to an enclosure, then merge the two enclosures
   15278           0 :                             auto &thisEnclosure = Enclosures(thisSideEnclosureNum);
   15279           0 :                             auto &otherEnclosure = Enclosures(otherSideEnclosureNum);
   15280           0 :                             for (const auto &zName : thisEnclosure.spaceNames) {
   15281           0 :                                 otherEnclosure.spaceNames.push_back(zName);
   15282           0 :                             }
   15283           0 :                             for (int zNum : thisEnclosure.spaceNums) {
   15284           0 :                                 otherEnclosure.spaceNums.push_back(zNum);
   15285           0 :                                 if (radiantSetup) {
   15286           0 :                                     state.dataHeatBal->space(zNum).radiantEnclosureNum = otherSideEnclosureNum;
   15287             :                                 } else {
   15288           0 :                                     state.dataHeatBal->space(zNum).solarEnclosureNum = otherSideEnclosureNum;
   15289             :                                 }
   15290           0 :                             }
   15291           0 :                             otherEnclosure.FloorArea += thisEnclosure.FloorArea;
   15292           0 :                             otherEnclosure.ExtWindowArea += thisEnclosure.ExtWindowArea;
   15293           0 :                             otherEnclosure.TotalSurfArea += thisEnclosure.TotalSurfArea;
   15294             :                             // Move any enclosures beyond thisEnclosure down one slot - at this point all enclosures are named "Radiant
   15295             :                             // Enclosure N"
   15296           0 :                             for (int enclNum = thisSideEnclosureNum; enclNum < enclosureNum; ++enclNum) {
   15297           0 :                                 std::string saveName = Enclosures(enclNum).Name;
   15298           0 :                                 Enclosures(enclNum) = Enclosures(enclNum + 1);
   15299           0 :                                 Enclosures(enclNum).Name = saveName;
   15300           0 :                                 for (int sNum : Enclosures(enclNum).spaceNums) {
   15301           0 :                                     if (radiantSetup) {
   15302           0 :                                         state.dataHeatBal->space(sNum).radiantEnclosureNum = enclNum;
   15303             :                                     } else {
   15304           0 :                                         state.dataHeatBal->space(sNum).solarEnclosureNum = enclNum;
   15305             :                                     }
   15306           0 :                                 }
   15307           0 :                             }
   15308             :                             // Clear the last rad enclosure and reduce the total number of enclosures by 1
   15309           0 :                             Enclosures(enclosureNum).Name.clear();
   15310           0 :                             Enclosures(enclosureNum).spaceNames.clear();
   15311           0 :                             Enclosures(enclosureNum).spaceNums.clear();
   15312           0 :                             Enclosures(enclosureNum).FloorArea = 0;
   15313           0 :                             Enclosures(enclosureNum).ExtWindowArea = 0;
   15314           0 :                             Enclosures(enclosureNum).TotalSurfArea = 0;
   15315           0 :                             enclosureNum -= 1;
   15316             :                         }
   15317             :                     } else {
   15318           0 :                         ErrorsFound = true;
   15319           0 :                         ShowSevereError(state, format("{}: Surface={} uses Construction:AirBoundary with illegal option:", RoutineName, surf.Name));
   15320           0 :                         if (radiantSetup) {
   15321           0 :                             ShowContinueError(state, "Radiant Exchange Method must be either GroupedSpaces or IRTSurface.");
   15322             :                         } else {
   15323           0 :                             ShowContinueError(state, "Solar and Daylighting Method must be either GroupedSpaces or InteriorWindow");
   15324             :                         }
   15325             :                     }
   15326          36 :                     if (solarSetup && constr.TypeIsAirBoundaryMixing) {
   15327             :                         // Set up mixing air boundaries only once, during solar setup
   15328          12 :                         int spaceNum1 = min(surf.spaceNum, state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
   15329          12 :                         int spaceNum2 = max(surf.spaceNum, state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
   15330             :                         // This pair already saved?
   15331          12 :                         bool found = false;
   15332          24 :                         for (auto const &thisAirBoundaryMixing : state.dataHeatBal->airBoundaryMixing) {
   15333          18 :                             if ((spaceNum1 == thisAirBoundaryMixing.space1) && (spaceNum2 == thisAirBoundaryMixing.space2)) {
   15334           6 :                                 found = true;
   15335           6 :                                 break;
   15336             :                             }
   15337          12 :                         }
   15338          12 :                         if (!found) {
   15339             :                             // Store the space pairs, schedule, and flow rate to use later to create cross mixing objects
   15340             :                             DataHeatBalance::AirBoundaryMixingSpecs newAirBoundaryMixing;
   15341           6 :                             newAirBoundaryMixing.space1 = spaceNum1;
   15342           6 :                             newAirBoundaryMixing.space2 = spaceNum2;
   15343           6 :                             newAirBoundaryMixing.scheduleIndex = state.dataConstruction->Construct(surf.Construction).AirBoundaryMixingSched;
   15344           6 :                             Real64 mixingVolume = state.dataConstruction->Construct(surf.Construction).AirBoundaryACH *
   15345           6 :                                                   min(state.dataHeatBal->space(spaceNum1).Volume, state.dataHeatBal->space(spaceNum2).Volume) /
   15346           6 :                                                   Constant::SecInHour;
   15347           6 :                             newAirBoundaryMixing.mixingVolumeFlowRate = mixingVolume;
   15348           6 :                             state.dataHeatBal->airBoundaryMixing.push_back(newAirBoundaryMixing);
   15349             :                         }
   15350             :                     }
   15351             :                 }
   15352             :             }
   15353          10 :             if (errorCount > 0) {
   15354           0 :                 ShowSevereError(state, format("{}: {} surfaces use Construction:AirBoundary in non-interzone surfaces.", RoutineName, errorCount));
   15355           0 :                 ShowContinueError(state, "For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;");
   15356             :             }
   15357             :         }
   15358             :         // Check for any spaces defined only by floor surface(s) and group them
   15359       11704 :         for (auto const &zone : state.dataHeatBal->Zone) {
   15360       10112 :             int newEnclosureNum = 0;
   15361       20248 :             for (int const spaceNum : zone.spaceIndexes) {
   15362       10136 :                 int spaceEnclosureNum = 0;
   15363       10136 :                 bool spaceHasOnlyFloors = false;
   15364       10136 :                 if (radiantSetup) {
   15365        5068 :                     spaceEnclosureNum = state.dataHeatBal->space(spaceNum).radiantEnclosureNum;
   15366             :                 } else {
   15367        5068 :                     spaceEnclosureNum = state.dataHeatBal->space(spaceNum).solarEnclosureNum;
   15368             :                 }
   15369       10136 :                 if (spaceEnclosureNum == 0) {
   15370       10112 :                     spaceHasOnlyFloors = true;
   15371       10458 :                     for (int const surfNum : state.dataHeatBal->space(spaceNum).surfaces) {
   15372       10446 :                         if (state.dataSurface->Surface(surfNum).Class == SurfaceClass::IntMass) continue;
   15373       10438 :                         if (state.dataSurface->Surface(surfNum).Class != SurfaceClass::Floor) {
   15374       10100 :                             spaceHasOnlyFloors = false;
   15375       10100 :                             break;
   15376             :                         }
   15377       10112 :                     }
   15378             :                 }
   15379       10136 :                 if (spaceEnclosureNum == 0 && spaceHasOnlyFloors) {
   15380          12 :                     anyGroupedSpaces = true;
   15381          12 :                     if (newEnclosureNum == 0) {
   15382             :                         // Assign one new enclosure for all loose floors in this zone
   15383           6 :                         ++enclosureNum;
   15384           6 :                         newEnclosureNum = enclosureNum;
   15385             :                     }
   15386          12 :                     if (radiantSetup) {
   15387           6 :                         state.dataHeatBal->space(spaceNum).radiantEnclosureNum = enclosureNum;
   15388             :                     } else {
   15389           6 :                         state.dataHeatBal->space(spaceNum).solarEnclosureNum = enclosureNum;
   15390             :                     }
   15391          12 :                     auto &thisEnclosure = Enclosures(enclosureNum);
   15392             :                     // Give this enclosure the zone name and assign this to the zone-remainder space if it exists
   15393          12 :                     thisEnclosure.Name = zone.Name;
   15394          12 :                     thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(spaceNum).Name);
   15395          12 :                     thisEnclosure.spaceNums.push_back(spaceNum);
   15396          12 :                     thisEnclosure.FloorArea = state.dataHeatBal->space(spaceNum).FloorArea;
   15397          12 :                     thisEnclosure.ExtWindowArea = state.dataHeatBal->space(spaceNum).extWindowArea;
   15398          12 :                     thisEnclosure.TotalSurfArea = state.dataHeatBal->space(spaceNum).totalSurfArea;
   15399             :                 }
   15400       10112 :             }
   15401        1592 :         }
   15402             : 
   15403        1592 :         if (anyGroupedSpaces) {
   15404             :             // All grouped spaces have been assigned to an enclosure, now assign remaining spaces
   15405          94 :             for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
   15406          84 :                 auto &curSpace = state.dataHeatBal->space(spaceNum);
   15407          84 :                 int spaceEnclosureNum = 0;
   15408          84 :                 if (radiantSetup) {
   15409          42 :                     spaceEnclosureNum = curSpace.radiantEnclosureNum;
   15410             :                 } else {
   15411          42 :                     spaceEnclosureNum = curSpace.solarEnclosureNum;
   15412             :                 }
   15413          84 :                 if (spaceEnclosureNum == 0) {
   15414          48 :                     if (Util::SameString(curSpace.Name, state.dataHeatBal->Zone(curSpace.zoneNum).Name + "-REMAINDER")) {
   15415             :                         // Search for existing enclosure with same name as the zone
   15416           6 :                         spaceEnclosureNum = Util::FindItemInList(state.dataHeatBal->Zone(curSpace.zoneNum).Name, Enclosures);
   15417             :                     }
   15418          48 :                     if (spaceEnclosureNum == 0) {
   15419             :                         // Otherwise add a new one named for the space
   15420          42 :                         ++enclosureNum;
   15421          42 :                         spaceEnclosureNum = enclosureNum;
   15422          42 :                         Enclosures(spaceEnclosureNum).Name = curSpace.Name;
   15423             :                     }
   15424          48 :                     if (radiantSetup) {
   15425          24 :                         curSpace.radiantEnclosureNum = spaceEnclosureNum;
   15426             :                     } else {
   15427          24 :                         curSpace.solarEnclosureNum = spaceEnclosureNum;
   15428             :                     }
   15429          48 :                     auto &thisEnclosure = Enclosures(spaceEnclosureNum);
   15430          48 :                     thisEnclosure.spaceNames.push_back(curSpace.Name);
   15431          48 :                     thisEnclosure.spaceNums.push_back(spaceNum);
   15432          48 :                     thisEnclosure.FloorArea += curSpace.FloorArea;
   15433          48 :                     thisEnclosure.ExtWindowArea += curSpace.extWindowArea;
   15434          48 :                     thisEnclosure.TotalSurfArea += curSpace.totalSurfArea;
   15435             :                 }
   15436             :             }
   15437          10 :             if (radiantSetup) {
   15438           5 :                 state.dataViewFactor->NumOfRadiantEnclosures = enclosureNum;
   15439             :             } else {
   15440           5 :                 state.dataViewFactor->NumOfSolarEnclosures = enclosureNum;
   15441             :             }
   15442             :         } else {
   15443             :             // There are no grouped radiant air boundaries, assign each space to it's own radiant enclosure
   15444       11634 :             for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
   15445       10052 :                 auto &thisEnclosure = Enclosures(spaceNum);
   15446       10052 :                 thisEnclosure.Name = state.dataHeatBal->space(spaceNum).Name;
   15447       10052 :                 thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(spaceNum).Name);
   15448       10052 :                 thisEnclosure.spaceNums.push_back(spaceNum);
   15449       10052 :                 thisEnclosure.FloorArea = state.dataHeatBal->space(spaceNum).FloorArea;
   15450       10052 :                 if (radiantSetup) {
   15451        5026 :                     state.dataHeatBal->space(spaceNum).radiantEnclosureNum = spaceNum;
   15452             :                 } else {
   15453        5026 :                     state.dataHeatBal->space(spaceNum).solarEnclosureNum = spaceNum;
   15454        5026 :                     thisEnclosure.ExtWindowArea = state.dataHeatBal->space(spaceNum).extWindowArea;
   15455        5026 :                     thisEnclosure.TotalSurfArea = state.dataHeatBal->space(spaceNum).totalSurfArea;
   15456             :                 }
   15457             :             }
   15458        1582 :             if (radiantSetup) {
   15459         791 :                 state.dataViewFactor->NumOfRadiantEnclosures = state.dataGlobal->numSpaces;
   15460             :             } else {
   15461         791 :                 state.dataViewFactor->NumOfSolarEnclosures = state.dataGlobal->numSpaces;
   15462             :             }
   15463             :         }
   15464        1592 :         if (radiantSetup) {
   15465         796 :             assert(state.dataViewFactor->NumOfRadiantEnclosures <= int(Enclosures.size()));
   15466         796 :             Enclosures.resize(state.dataViewFactor->NumOfRadiantEnclosures);
   15467             :         } else {
   15468         796 :             assert(state.dataViewFactor->NumOfSolarEnclosures <= int(Enclosures.size()));
   15469         796 :             Enclosures.resize(state.dataViewFactor->NumOfSolarEnclosures);
   15470             :         }
   15471             : 
   15472       11702 :         for (auto &thisEnclosure : state.dataViewFactor->EnclRadInfo) {
   15473       20220 :             SetupOutputVariable(state,
   15474             :                                 "Enclosure Mean Radiant Temperature",
   15475             :                                 Constant::Units::C,
   15476       10110 :                                 thisEnclosure.MRT,
   15477             :                                 OutputProcessor::TimeStepType::Zone,
   15478             :                                 OutputProcessor::StoreType::Average,
   15479       10110 :                                 thisEnclosure.Name);
   15480        1592 :         }
   15481             : 
   15482             :         // TODO MJW: For now, set the max and min enclosure numbers for each zone to be used in CalcInteriorRadExchange with ZoneToResimulate
   15483       11704 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   15484       20248 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   15485       10136 :                 if (state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst == -1) { // initial value
   15486        5056 :                     state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst = state.dataHeatBal->space(spaceNum).radiantEnclosureNum;
   15487             :                 } else {
   15488        5080 :                     state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst =
   15489        5080 :                         min(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst, state.dataHeatBal->space(spaceNum).radiantEnclosureNum);
   15490             :                 }
   15491       10136 :                 state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast =
   15492       10136 :                     max(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast, state.dataHeatBal->space(spaceNum).radiantEnclosureNum);
   15493       10112 :             }
   15494       10112 :             assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst != -1);
   15495       10112 :             assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast != -1);
   15496       10112 :             assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst <= state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast);
   15497             :         }
   15498        1592 :     }
   15499             : 
   15500       42201 :     void CheckConvexity(EnergyPlusData &state,
   15501             :                         int const SurfNum, // Current surface number
   15502             :                         int const NSides   // Number of sides to figure
   15503             :     )
   15504             :     {
   15505             :         // SUBROUTINE INFORMATION:
   15506             :         //       AUTHOR         Tyler Hoyt
   15507             :         //       DATE WRITTEN   December 2010
   15508             :         //       MODIFIED       CR8752 - incorrect note of non-convex polygons
   15509             :         //       RE-ENGINEERED  na
   15510             : 
   15511             :         // PURPOSE OF THIS SUBROUTINE: This subroutine verifies the convexity of a
   15512             :         // surface that is exposed to the sun in the case that full shading calculations
   15513             :         // are required. The calculation conveniently detects collinear points as well,
   15514             :         // and returns a list of indices that are collinear within the plane of the surface.
   15515             : 
   15516             :         // METHODOLOGY EMPLOYED: First the surface is determined to have dimension 2 in
   15517             :         // either the xy, yz, or xz plane. That plane is selected to do the testing.
   15518             :         // Vectors representing the edges of the polygon and the perpendicular dot product
   15519             :         // between adjacent edges are computed. This allows the turning angle to be determined.
   15520             :         // If the turning angle is greater than pi/2, it turns to the right, and if it is
   15521             :         // less than pi/2, it turns left. The direction of the turn is stored, and if it
   15522             :         // changes as the edges are iterated the surface is not convex. Meanwhile it stores
   15523             :         // the indices of vertices that are collinear and are later removed.
   15524             : 
   15525             :         // REFERENCES:
   15526             :         // http://mathworld.wolfram.com/ConvexPolygon.html
   15527             : 
   15528             :         // Using/Aliasing
   15529             : 
   15530             :         using namespace DataErrorTracking;
   15531             : 
   15532       42201 :         constexpr Real64 TurnThreshold(0.000001); // Sensitivity of convexity test, in radians
   15533             : 
   15534       42201 :         Real64 LastTheta = 0.0;                 // Angle between edge vectors
   15535             :         bool SignFlag;                          // Direction of edge turn : true is right, false is left
   15536       42201 :         bool PrevSignFlag(false);               // Container for the sign of the previous iteration's edge turn
   15537       42201 :         bool PrevSignFlagInitialized(false);    // Whether we picked a PrevSignFlag already or not
   15538       42201 :         auto &X = state.dataSurfaceGeometry->X; // containers for x,y,z vertices of the surface
   15539       42201 :         auto &Y = state.dataSurfaceGeometry->Y;
   15540       42201 :         auto &Z = state.dataSurfaceGeometry->Z;
   15541       42201 :         auto &A = state.dataSurfaceGeometry->A; // containers for convexity test
   15542       42201 :         auto &B = state.dataSurfaceGeometry->B;
   15543       42201 :         auto &VertSize = state.dataSurfaceGeometry->VertSize; // size of X,Y,Z,A,B arrays
   15544             : 
   15545       42201 :         std::vector<int> surfCollinearVerts; // index of vertices to remove, 1-indexed
   15546       42201 :         surfCollinearVerts.reserve(NSides + 2);
   15547             : 
   15548       42201 :         if (state.dataSurfaceGeometry->CheckConvexityFirstTime) {
   15549         760 :             X.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15550         760 :             Y.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15551         760 :             Z.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15552         760 :             A.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15553         760 :             B.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15554         760 :             VertSize = state.dataSurface->MaxVerticesPerSurface;
   15555         760 :             state.dataSurfaceGeometry->CheckConvexityFirstTime = false;
   15556             :         }
   15557             : 
   15558       42201 :         if (NSides > VertSize) {
   15559          33 :             X.deallocate();
   15560          33 :             Y.deallocate();
   15561          33 :             Z.deallocate();
   15562          33 :             A.deallocate();
   15563          33 :             B.deallocate();
   15564          33 :             X.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15565          33 :             Y.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15566          33 :             Z.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15567          33 :             A.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15568          33 :             B.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
   15569          33 :             VertSize = state.dataSurface->MaxVerticesPerSurface;
   15570             :         }
   15571             : 
   15572       42201 :         auto &surfaceTmp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
   15573       42201 :         auto &vertices = surfaceTmp.Vertex;
   15574             : 
   15575      211868 :         for (int n = 1; n <= NSides; ++n) {
   15576      169667 :             X(n) = vertices(n).x;
   15577      169667 :             Y(n) = vertices(n).y;
   15578      169667 :             Z(n) = vertices(n).z;
   15579             :         }
   15580       42201 :         X(NSides + 1) = vertices(1).x;
   15581       42201 :         Y(NSides + 1) = vertices(1).y;
   15582       42201 :         Z(NSides + 1) = vertices(1).z;
   15583       42201 :         X(NSides + 2) = vertices(2).x;
   15584       42201 :         Y(NSides + 2) = vertices(2).y;
   15585       42201 :         Z(NSides + 2) = vertices(2).z;
   15586             : 
   15587             :         // Determine a suitable plane in which to do the tests
   15588       42201 :         Real64 Det = 0.0;
   15589      211868 :         for (int n = 1; n <= NSides; ++n) {
   15590      169667 :             Det += X(n) * Y(n + 1) - X(n + 1) * Y(n);
   15591             :         }
   15592       42201 :         if (std::abs(Det) > Constant::SmallDistance) {
   15593       13648 :             A = X;
   15594       13648 :             B = Y;
   15595             :         } else {
   15596       28553 :             Det = 0.0;
   15597      142669 :             for (int n = 1; n <= NSides; ++n) {
   15598      114116 :                 Det += X(n) * Z(n + 1) - X(n + 1) * Z(n);
   15599             :             }
   15600       28553 :             if (std::abs(Det) > Constant::SmallDistance) {
   15601       19242 :                 A = X;
   15602       19242 :                 B = Z;
   15603             :             } else {
   15604        9311 :                 Det = 0.0;
   15605       46487 :                 for (int n = 1; n <= NSides; ++n) {
   15606       37176 :                     Det += Y(n) * Z(n + 1) - Y(n + 1) * Z(n);
   15607             :                 }
   15608        9311 :                 if (std::abs(Det) > Constant::SmallDistance) {
   15609        9311 :                     A = Y;
   15610        9311 :                     B = Z;
   15611             :                 } else {
   15612             :                     // This condition should not be reached if the surfaces are guaranteed to be planar already
   15613           0 :                     ShowSevereError(state, format("CheckConvexity: Surface=\"{}\" is non-planar.", surfaceTmp.Name));
   15614           0 :                     ShowContinueError(state, "Coincident Vertices will be removed as possible.");
   15615           0 :                     for (int n = 1; n <= surfaceTmp.Sides; ++n) {
   15616           0 :                         auto const &point = vertices(n);
   15617             :                         static constexpr std::string_view ErrFmt = " ({:8.3F},{:8.3F},{:8.3F})";
   15618           0 :                         ShowContinueError(state, format(ErrFmt, point.x, point.y, point.z));
   15619             :                     }
   15620             :                 }
   15621             :             }
   15622             :         }
   15623             : 
   15624      211868 :         for (int n = 1; n <= NSides; ++n) { // perform convexity test in the plane determined above.
   15625             : 
   15626      169667 :             DataVectorTypes::Vector_2d pt0(A(n), B(n));
   15627      169667 :             DataVectorTypes::Vector_2d pt1(A(n + 1), B(n + 1));
   15628      169667 :             DataVectorTypes::Vector_2d pt2(A(n + 2), B(n + 2));
   15629             : 
   15630      169667 :             DataVectorTypes::Vector_2d V1 = pt1 - pt0;
   15631      169667 :             DataVectorTypes::Vector_2d V2 = pt2 - pt1;
   15632             : 
   15633      169667 :             Real64 V1len = V1.length(); // = norm_L2()
   15634      169667 :             Real64 V2len = V2.length();
   15635      169667 :             if (V1len <= 1.e-8 || V2len <= 1.e-8) {
   15636             :                 // At least two points are coincident. Should this happen? GetVertices is supposed to pop these vertices
   15637           0 :                 continue;
   15638             :             }
   15639      169667 :             Real64 CrossProd = V1.cross(V2);
   15640      169667 :             Real64 sinarg = CrossProd / (V1len * V2len);
   15641      169667 :             if (sinarg < -1.0) {
   15642         884 :                 sinarg = -1.0;
   15643      168783 :             } else if (sinarg > 1.0) {
   15644         660 :                 sinarg = 1.0;
   15645             :             }
   15646      169667 :             Real64 Theta = std::asin(sinarg);
   15647      169667 :             if (Theta > TurnThreshold) {
   15648       83886 :                 SignFlag = true;
   15649       85781 :             } else if (Theta < -TurnThreshold) {
   15650       85781 :                 SignFlag = false;
   15651             :             } else { // std::abs(Theta) < TurnThreshold
   15652             :                 // Store the index of the collinear vertex for removal
   15653           0 :                 int colinearIndex = n + 1;
   15654           0 :                 if (colinearIndex > NSides) {
   15655           0 :                     colinearIndex -= NSides;
   15656             :                 }
   15657           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   15658           0 :                     ShowWarningError(
   15659             :                         state,
   15660           0 :                         format("CheckConvexity: Surface=\"{}\", vertex {} is colinear with previous and next.", surfaceTmp.Name, colinearIndex));
   15661             :                 }
   15662           0 :                 ++state.dataErrTracking->TotalCoincidentVertices;
   15663           0 :                 surfCollinearVerts.push_back(colinearIndex);
   15664           0 :                 continue;
   15665           0 :             }
   15666             : 
   15667      169667 :             if (!PrevSignFlagInitialized) {
   15668       42201 :                 PrevSignFlag = SignFlag;
   15669       42201 :                 LastTheta = Theta;
   15670       42201 :                 PrevSignFlagInitialized = true;
   15671       42201 :                 continue;
   15672             :             }
   15673             : 
   15674      127466 :             if (SignFlag != PrevSignFlag) {
   15675         801 :                 if (state.dataGlobal->DisplayExtraWarnings && surfaceTmp.ExtSolar &&
   15676           0 :                     (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) && surfaceTmp.IsConvex &&
   15677         801 :                     !state.dataSysVars->SutherlandHodgman &&
   15678           0 :                     (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PolygonClipping)) {
   15679           0 :                     ShowWarningError(state,
   15680           0 :                                      format("CheckConvexity: Zone=\"{}\", Surface=\"{}\" is non-convex.",
   15681           0 :                                             state.dataHeatBal->Zone(surfaceTmp.Zone).Name,
   15682           0 :                                             surfaceTmp.Name));
   15683           0 :                     int Np1 = n + 1;
   15684           0 :                     if (Np1 > NSides) {
   15685           0 :                         Np1 -= NSides;
   15686             :                     }
   15687           0 :                     int Np2 = n + 2;
   15688           0 :                     if (Np2 > NSides) {
   15689           0 :                         Np2 -= NSides;
   15690             :                     }
   15691           0 :                     ShowContinueError(state, format("...vertex {} to vertex {} to vertex {}", n, Np1, Np2));
   15692           0 :                     ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", n, X(n), Y(n), Z(n)));
   15693           0 :                     ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", Np1, X(n + 1), Y(n + 1), Z(n + 1)));
   15694           0 :                     ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", Np2, X(n + 2), Y(n + 2), Z(n + 2)));
   15695             :                     // ShowContinueError(state, format("...theta angle=[{:.6R}]", Theta));
   15696             :                     // ShowContinueError(state, format("...last theta angle=[{:.6R}]", LastTheta));
   15697             :                 }
   15698         801 :                 surfaceTmp.IsConvex = false;
   15699             :                 // #10103 - We do not want to break early, because we do want to consistently remove colinear vertices
   15700             :                 // to avoid potential vertex size mismatch fatal errors
   15701             :                 // break;
   15702             :             }
   15703      127466 :             PrevSignFlag = SignFlag;
   15704      127466 :             LastTheta = Theta;
   15705      338471 :         }
   15706             : 
   15707             :         // must check to make sure don't remove NSides below 3
   15708       42201 :         int M = surfCollinearVerts.size();
   15709       42201 :         if (M > 0) { // Remove the collinear points determined above
   15710           0 :             if (NSides - M >= 3) {
   15711           0 :                 surfaceTmp.Sides = NSides - M;
   15712           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   15713           0 :                     ShowWarningError(state,
   15714           0 :                                      format("CheckConvexity: Surface=\"{}\" has [{}] collinear points that have been removed.", surfaceTmp.Name, M));
   15715             :                 }
   15716             :             } else { // too many
   15717           0 :                 if (state.dataGlobal->DisplayExtraWarnings) {
   15718           0 :                     ShowWarningError(state, format("CheckConvexity: Surface=\"{}\" has [{}] collinear points.", surfaceTmp.Name, M));
   15719           0 :                     ShowContinueError(state, "...too many to remove all.  Will leave the surface with 3 sides. But this is now a degenerate surface");
   15720             :                 }
   15721           0 :                 ++state.dataErrTracking->TotalDegenerateSurfaces;
   15722           0 :                 surfaceTmp.Sides = 3; // max(NSides - M, 3) = 3 since NSide - M is < 3;
   15723           0 :                 surfCollinearVerts.resize(NSides - 3);
   15724             :             }
   15725             : 
   15726             :             // remove duplicated points: For that we construct a new array of vertices, only copying indices that aren't in SurfCollinearVerts
   15727             :             // Then we move that array into the original one
   15728           0 :             Array1D<Vector> newVertices;
   15729           0 :             newVertices.allocate(surfaceTmp.Sides);
   15730             : 
   15731           0 :             int n = 0;
   15732           0 :             for (int i = 1; i <= NSides; ++i) {
   15733           0 :                 if (std::find(surfCollinearVerts.cbegin(), surfCollinearVerts.cend(), i) == surfCollinearVerts.cend()) {
   15734           0 :                     newVertices(++n) = vertices(i);
   15735             :                 }
   15736             :             }
   15737           0 :             vertices = std::move(newVertices);
   15738             : 
   15739           0 :             if (state.dataGlobal->DisplayExtraWarnings) {
   15740           0 :                 ShowWarningError(state,
   15741           0 :                                  format("CheckConvexity: Surface=\"{}\": The vertex points has been reprocessed as Sides = {}",
   15742           0 :                                         surfaceTmp.Name,
   15743           0 :                                         surfaceTmp.Sides));
   15744             :             }
   15745           0 :         }
   15746       42201 :     }
   15747             : 
   15748       43251 :     bool isRectangle(EnergyPlusData &state, int const ThisSurf // Surface number
   15749             :     )
   15750             :     {
   15751             :         // SUBROUTINE INFORMATION:
   15752             :         //       AUTHOR         M.J. Witte
   15753             :         //       DATE WRITTEN   October 2015
   15754             : 
   15755             :         // PURPOSE: Check if a 4-sided surface is a rectangle
   15756             : 
   15757             :         using namespace Vectors;
   15758             : 
   15759             :         Real64 Diagonal1;                                                // Length of diagonal of 4-sided figure from vertex 1 to vertex 3 (m)
   15760             :         Real64 Diagonal2;                                                // Length of diagonal of 4-sided figure from vertex 2 to vertex 4 (m)
   15761             :         Real64 DotProd;                                                  // Dot product of two adjacent sides - to test for right angle
   15762       43251 :         Real64 const cos89deg = std::cos(89.0 * Constant::DegToRadians); // tolerance for right angle
   15763       43251 :         Vector Vect32;                                                   // normalized vector from vertex 3 to vertex 2
   15764       43251 :         Vector Vect21;                                                   // normalized vector from vertex 2 to vertex 1
   15765             : 
   15766       43251 :         auto &surf = state.dataSurface->Surface(ThisSurf);
   15767       43251 :         Diagonal1 = VecLength(surf.Vertex(1) - surf.Vertex(3));
   15768       43251 :         Diagonal2 = VecLength(surf.Vertex(2) - surf.Vertex(4));
   15769             :         // Test for rectangularity
   15770       43251 :         if (std::abs(Diagonal1 - Diagonal2) < 0.020) { // This tolerance based on coincident vertex tolerance of 0.01
   15771       41806 :             Vect32 = VecNormalize(surf.Vertex(3) - surf.Vertex(2));
   15772       41806 :             Vect21 = VecNormalize(surf.Vertex(2) - surf.Vertex(1));
   15773       41806 :             DotProd = dot(Vect32, Vect21);
   15774       41806 :             if (std::abs(DotProd) <= cos89deg) {
   15775       38007 :                 return true;
   15776             :             } else {
   15777        3799 :                 return false;
   15778             :             }
   15779             :         } else {
   15780        1445 :             return false;
   15781             :         }
   15782       43251 :     }
   15783             : 
   15784           1 :     void MakeEquivalentRectangle(EnergyPlusData &state,
   15785             :                                  int const SurfNum, // Surface number
   15786             :                                  bool &ErrorsFound  // Error flag indicator (true if errors found)
   15787             :     )
   15788             :     {
   15789             :         // SUBROUTINE INFORMATION:
   15790             :         //       AUTHOR         R. Zhang, LBNL
   15791             :         //       DATE WRITTEN   September 2016
   15792             :         //       MODIFIED       na
   15793             :         //       RE-ENGINEERED  na
   15794             : 
   15795             :         // PURPOSE OF THIS SUBROUTINE:
   15796             :         // Processing of 4-sided but non-rectangular Window, Door or GlassDoor.
   15797             :         // Calculate the effective height and width of the surface.
   15798             :         //
   15799             :         // METHODOLOGY EMPLOYED:
   15800             :         // Transform the surface into an equivalent rectangular surface with the same area and aspect ratio.
   15801             : 
   15802             :         Real64 BaseCosAzimuth;
   15803             :         Real64 BaseCosTilt;
   15804             :         Real64 BaseSinAzimuth;
   15805             :         Real64 BaseSinTilt;
   15806             :         Real64 SurfWorldAz;
   15807             :         Real64 SurfTilt;
   15808             :         Real64 AspectRatio;  // Aspect ratio
   15809             :         Real64 NumSurfSides; // Number of surface sides
   15810             :         Real64 WidthEff;     // Effective width of the surface
   15811             :         Real64 WidthMax;     // X difference between the vertex on the most left and the one on the most right
   15812             :         Real64 HeightEff;    // Effective height of the surface
   15813             :         Real64 HeightMax;    // Y difference between the lowest and toppest vertices
   15814             :         Real64 Xp;
   15815             :         Real64 Yp;
   15816             :         Real64 Zp;
   15817             :         Real64 XLLC;
   15818             :         Real64 YLLC;
   15819             :         Real64 ZLLC;
   15820             : 
   15821           1 :         if (SurfNum == 0) {
   15822             :             // invalid surface
   15823           0 :             ErrorsFound = true;
   15824           0 :             return;
   15825             :         }
   15826             : 
   15827           1 :         auto &surf = state.dataSurface->Surface(SurfNum);
   15828           1 :         if (surf.Sides != 4) {
   15829             :             // the method is designed for 4-sided surface
   15830           0 :             return;
   15831           1 :         } else if (isRectangle(state, SurfNum)) {
   15832             :             // no need to transform
   15833           0 :             return;
   15834             :         }
   15835             : 
   15836           1 :         SurfWorldAz = surf.Azimuth;
   15837           1 :         SurfTilt = surf.Tilt;
   15838           1 :         BaseCosAzimuth = std::cos(SurfWorldAz * Constant::DegToRadians);
   15839           1 :         BaseSinAzimuth = std::sin(SurfWorldAz * Constant::DegToRadians);
   15840           1 :         BaseCosTilt = std::cos(SurfTilt * Constant::DegToRadians);
   15841           1 :         BaseSinTilt = std::sin(SurfTilt * Constant::DegToRadians);
   15842           1 :         NumSurfSides = surf.Sides;
   15843             : 
   15844             :         // Calculate WidthMax and HeightMax
   15845           1 :         WidthMax = 0.0;
   15846           1 :         HeightMax = 0.0;
   15847           4 :         for (int i = 1; i < NumSurfSides; ++i) {
   15848           9 :             for (int j = i + 1; j <= NumSurfSides; ++j) {
   15849             : 
   15850           6 :                 Xp = surf.Vertex(j).x - surf.Vertex(i).x;
   15851           6 :                 Yp = surf.Vertex(j).y - surf.Vertex(i).y;
   15852           6 :                 Zp = surf.Vertex(j).z - surf.Vertex(i).z;
   15853             : 
   15854           6 :                 XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
   15855           6 :                 YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
   15856           6 :                 ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
   15857             : 
   15858           6 :                 if (std::abs(XLLC) > WidthMax) WidthMax = std::abs(XLLC);
   15859           6 :                 if (std::abs(YLLC) > WidthMax) HeightMax = std::abs(YLLC);
   15860             :             }
   15861             :         }
   15862             : 
   15863             :         // Perform transformation by calculating WidthEff and HeightEff
   15864           1 :         if ((WidthMax > 0) && (HeightMax > 0)) {
   15865           1 :             AspectRatio = WidthMax / HeightMax;
   15866             :         } else {
   15867           0 :             AspectRatio = 1;
   15868             :         }
   15869           1 :         WidthEff = std::sqrt(surf.Area * AspectRatio);
   15870           1 :         HeightEff = std::sqrt(surf.Area / AspectRatio);
   15871             : 
   15872             :         // Assign the effective width and length to the surface
   15873           1 :         surf.Width = WidthEff;
   15874           1 :         surf.Height = HeightEff;
   15875             :     }
   15876             : 
   15877        8915 :     void CheckForReversedLayers(EnergyPlusData &state,
   15878             :                                 bool &RevLayerDiffs,    // true when differences are discovered in interzone constructions
   15879             :                                 int const ConstrNum,    // construction index
   15880             :                                 int const ConstrNumRev, // construction index for reversed construction
   15881             :                                 int const TotalLayers   // total layers for construction definition
   15882             :     )
   15883             :     {
   15884        8915 :         RevLayerDiffs = false;
   15885             : 
   15886       27825 :         for (int LayerNo = 1; LayerNo <= TotalLayers; ++LayerNo) {
   15887             : 
   15888       18912 :             int thisConstLayer = state.dataConstruction->Construct(ConstrNum).LayerPoint(LayerNo);
   15889       18912 :             int revConstLayer = state.dataConstruction->Construct(ConstrNumRev).LayerPoint(TotalLayers - LayerNo + 1);
   15890             : 
   15891       18912 :             auto *thisMatLay = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(thisConstLayer));
   15892       18912 :             assert(thisMatLay != nullptr);
   15893       18912 :             auto *revMatLay = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(revConstLayer));
   15894       18912 :             assert(revMatLay != nullptr);
   15895       18912 :             if ((thisConstLayer != revConstLayer) ||                   // Not pointing to the same layer
   15896       18910 :                 (thisMatLay->group == Material::Group::WindowGlass) || // Not window glass or glass equivalent layer which have
   15897       18903 :                 (revMatLay->group == Material::Group::WindowGlass) ||  // to have certain properties flipped from front to back
   15898       18903 :                 (thisMatLay->group == Material::Group::GlassEquivalentLayer) || (revMatLay->group == Material::Group::GlassEquivalentLayer)) {
   15899             :                 // If not point to the same layer, check to see if this is window glass which might need to have
   15900             :                 // front and back material properties reversed.
   15901           9 :                 Real64 constexpr SmallDiff = 0.0001;
   15902           9 :                 if ((thisMatLay->group == Material::Group::WindowGlass) && (revMatLay->group == Material::Group::WindowGlass)) {
   15903             :                     // Both layers are window glass, so need to check to see if the properties are reversed
   15904          14 :                     if ((abs(thisMatLay->Thickness - revMatLay->Thickness) > SmallDiff) ||
   15905          14 :                         (abs(thisMatLay->ReflectSolBeamBack - revMatLay->ReflectSolBeamFront) > SmallDiff) ||
   15906          14 :                         (abs(thisMatLay->ReflectSolBeamFront - revMatLay->ReflectSolBeamBack) > SmallDiff) ||
   15907          14 :                         (abs(thisMatLay->TransVis - revMatLay->TransVis) > SmallDiff) ||
   15908          14 :                         (abs(thisMatLay->ReflectVisBeamBack - revMatLay->ReflectVisBeamFront) > SmallDiff) ||
   15909          14 :                         (abs(thisMatLay->ReflectVisBeamFront - revMatLay->ReflectVisBeamBack) > SmallDiff) ||
   15910          14 :                         (abs(thisMatLay->TransThermal - revMatLay->TransThermal) > SmallDiff) ||
   15911          14 :                         (abs(thisMatLay->AbsorpThermalBack - revMatLay->AbsorpThermalFront) > SmallDiff) ||
   15912          14 :                         (abs(thisMatLay->AbsorpThermalFront - revMatLay->AbsorpThermalBack) > SmallDiff) ||
   15913          14 :                         (abs(thisMatLay->Conductivity - revMatLay->Conductivity) > SmallDiff) ||
   15914           7 :                         (abs(thisMatLay->GlassTransDirtFactor - revMatLay->GlassTransDirtFactor) > SmallDiff) ||
   15915          14 :                         (thisMatLay->SolarDiffusing != revMatLay->SolarDiffusing) ||
   15916          21 :                         (abs(thisMatLay->YoungModulus - revMatLay->YoungModulus) > SmallDiff) ||
   15917           7 :                         (abs(thisMatLay->PoissonsRatio - revMatLay->PoissonsRatio) > SmallDiff)) {
   15918           0 :                         RevLayerDiffs = true;
   15919           0 :                         break; // exit when diff
   15920             :                     }          // If none of the above conditions is met, then these should be the same layers in reverse (RevLayersDiffs = false)
   15921           2 :                 } else if ((thisMatLay->group == Material::Group::GlassEquivalentLayer) &&
   15922           0 :                            (revMatLay->group == Material::Group::GlassEquivalentLayer)) {
   15923           0 :                     if ((abs(thisMatLay->TausBackBeamBeam - revMatLay->TausFrontBeamBeam) > SmallDiff) ||
   15924           0 :                         (abs(thisMatLay->TausFrontBeamBeam - revMatLay->TausBackBeamBeam) > SmallDiff) ||
   15925           0 :                         (abs(thisMatLay->ReflBackBeamBeam - revMatLay->ReflFrontBeamBeam) > SmallDiff) ||
   15926           0 :                         (abs(thisMatLay->ReflFrontBeamBeam - revMatLay->ReflBackBeamBeam) > SmallDiff) ||
   15927           0 :                         (abs(thisMatLay->TausBackBeamBeamVis - revMatLay->TausFrontBeamBeamVis) > SmallDiff) ||
   15928           0 :                         (abs(thisMatLay->TausFrontBeamBeamVis - revMatLay->TausBackBeamBeamVis) > SmallDiff) ||
   15929           0 :                         (abs(thisMatLay->ReflBackBeamBeamVis - revMatLay->ReflFrontBeamBeamVis) > SmallDiff) ||
   15930           0 :                         (abs(thisMatLay->ReflFrontBeamBeamVis - revMatLay->ReflBackBeamBeamVis) > SmallDiff) ||
   15931           0 :                         (abs(thisMatLay->TausBackBeamDiff - revMatLay->TausFrontBeamDiff) > SmallDiff) ||
   15932           0 :                         (abs(thisMatLay->TausFrontBeamDiff - revMatLay->TausBackBeamDiff) > SmallDiff) ||
   15933           0 :                         (abs(thisMatLay->ReflBackBeamDiff - revMatLay->ReflFrontBeamDiff) > SmallDiff) ||
   15934           0 :                         (abs(thisMatLay->ReflFrontBeamDiff - revMatLay->ReflBackBeamDiff) > SmallDiff) ||
   15935           0 :                         (abs(thisMatLay->TausBackBeamDiffVis - revMatLay->TausFrontBeamDiffVis) > SmallDiff) ||
   15936           0 :                         (abs(thisMatLay->TausFrontBeamDiffVis - revMatLay->TausBackBeamDiffVis) > SmallDiff) ||
   15937           0 :                         (abs(thisMatLay->ReflBackBeamDiffVis - revMatLay->ReflFrontBeamDiffVis) > SmallDiff) ||
   15938           0 :                         (abs(thisMatLay->ReflFrontBeamDiffVis - revMatLay->ReflBackBeamDiffVis) > SmallDiff) ||
   15939           0 :                         (abs(thisMatLay->TausDiffDiff - revMatLay->TausDiffDiff) > SmallDiff) ||
   15940           0 :                         (abs(thisMatLay->ReflBackDiffDiff - revMatLay->ReflFrontDiffDiff) > SmallDiff) ||
   15941           0 :                         (abs(thisMatLay->ReflFrontDiffDiff - revMatLay->ReflBackDiffDiff) > SmallDiff) ||
   15942           0 :                         (abs(thisMatLay->TausDiffDiffVis - revMatLay->TausDiffDiffVis) > SmallDiff) ||
   15943           0 :                         (abs(thisMatLay->ReflBackDiffDiffVis - revMatLay->ReflFrontDiffDiffVis) > SmallDiff) ||
   15944           0 :                         (abs(thisMatLay->ReflFrontDiffDiffVis - revMatLay->ReflBackDiffDiffVis) > SmallDiff) ||
   15945           0 :                         (abs(thisMatLay->TausThermal - revMatLay->TausThermal) > SmallDiff) ||
   15946           0 :                         (abs(thisMatLay->EmissThermalBack - revMatLay->EmissThermalFront) > SmallDiff) ||
   15947           0 :                         (abs(thisMatLay->EmissThermalFront - revMatLay->EmissThermalBack) > SmallDiff) ||
   15948           0 :                         (abs(thisMatLay->Resistance - revMatLay->Resistance) > SmallDiff)) {
   15949           0 :                         RevLayerDiffs = true;
   15950           0 :                         break; // exit when diff
   15951             :                     }          // If none of the above conditions is met, then these should be the same layers in reverse (RevLayersDiffs = false)
   15952             :                 } else {
   15953             :                     // Other material types do not have reversed constructions so if they are not the same layer there is a problem
   15954             :                     // (RevLayersDiffs = true)
   15955           2 :                     RevLayerDiffs = true;
   15956           2 :                     break; // exit when diff
   15957             :                 }          // End check of whether or not these are WindowGlass
   15958             :             }              // else: thisConstLayer is the same as revConstLayer--so there is no problem (RevLayersDiffs = false)
   15959             :         }
   15960        8915 :     }
   15961             : 
   15962         796 :     void GetGeoSummaryRoof(EnergyPlusData &state, GeoSummary &geoSummaryRoof)
   15963             :     {
   15964         796 :         std::vector<Vector> uniqueRoofVertices;
   15965         796 :         std::vector<SurfaceGeometry::EdgeOfSurf> uniqEdgeOfSurfs; // I'm only partially using this
   15966       46840 :         for (const auto &surface : state.dataSurface->Surface) {
   15967             : 
   15968       46044 :             if (surface.ExtBoundCond != ExternalEnvironment) {
   15969       26609 :                 continue;
   15970             :             }
   15971       19435 :             if (!surface.HeatTransSurf) {
   15972        1635 :                 continue;
   15973             :             }
   15974             : 
   15975       17800 :             if (surface.Tilt > 45.0) { // TODO Double check tilt wrt outside vs inside?
   15976       15212 :                 continue;
   15977             :             }
   15978             : 
   15979        2588 :             Real64 const z_min(minval(surface.Vertex, &Vector::z));
   15980        2588 :             Real64 const z_max(maxval(surface.Vertex, &Vector::z));
   15981        2588 :             Real64 const verticalHeight = z_max - z_min;
   15982        2588 :             geoSummaryRoof.Height += verticalHeight * surface.Area;
   15983        2588 :             geoSummaryRoof.Tilt += surface.Tilt * surface.Area;
   15984        2588 :             geoSummaryRoof.Azimuth += surface.Azimuth * surface.Area;
   15985        2588 :             geoSummaryRoof.Area += surface.Area;
   15986             : 
   15987       13128 :             for (auto it = surface.Vertex.begin(); it != surface.Vertex.end(); ++it) {
   15988             : 
   15989       10540 :                 auto itnext = std::next(it);
   15990       10540 :                 if (itnext == std::end(surface.Vertex)) {
   15991        2588 :                     itnext = std::begin(surface.Vertex);
   15992             :                 }
   15993             : 
   15994       10540 :                 auto &curVertex = *it;
   15995       10540 :                 auto &nextVertex = *itnext;
   15996       21080 :                 auto it2 = std::find_if(uniqueRoofVertices.begin(), uniqueRoofVertices.end(), [&curVertex](const auto &unqV) {
   15997      381270 :                     return SurfaceGeometry::isAlmostEqual3dPt(curVertex, unqV);
   15998       21080 :                 });
   15999       10540 :                 if (it2 == std::end(uniqueRoofVertices)) {
   16000        7960 :                     uniqueRoofVertices.emplace_back(curVertex);
   16001             :                 }
   16002             : 
   16003       10540 :                 SurfaceGeometry::EdgeOfSurf thisEdge;
   16004       10540 :                 thisEdge.start = std::move(curVertex);
   16005       10540 :                 thisEdge.end = std::move(nextVertex);
   16006       10540 :                 thisEdge.count = 1;
   16007             : 
   16008             :                 // Uses the custom operator== that uses isAlmostEqual3dPt internally and doesn't care about order of the start/end
   16009       21080 :                 auto itEdge = std::find(uniqEdgeOfSurfs.begin(), uniqEdgeOfSurfs.end(), thisEdge);
   16010       10540 :                 if (itEdge == uniqEdgeOfSurfs.end()) {
   16011        9458 :                     uniqEdgeOfSurfs.emplace_back(std::move(thisEdge));
   16012             :                 } else {
   16013        1082 :                     ++(itEdge->count);
   16014             :                 }
   16015       10540 :             }
   16016         796 :         }
   16017             : 
   16018         796 :         if (geoSummaryRoof.Area > 0) {
   16019         744 :             geoSummaryRoof.Height /= geoSummaryRoof.Area;
   16020         744 :             geoSummaryRoof.Tilt /= geoSummaryRoof.Area;
   16021         744 :             geoSummaryRoof.Azimuth /= geoSummaryRoof.Area;
   16022             :         } else {
   16023          52 :             geoSummaryRoof.Height = 0.0;
   16024          52 :             geoSummaryRoof.Tilt = 0.0;
   16025          52 :             geoSummaryRoof.Azimuth = 0.0;
   16026             :         }
   16027             : 
   16028             :         // Remove the ones that are already used twice
   16029        1592 :         uniqEdgeOfSurfs.erase(
   16030       11050 :             std::remove_if(uniqEdgeOfSurfs.begin(), uniqEdgeOfSurfs.end(), [](const auto &edge) -> bool { return edge.count == 2; }),
   16031        1592 :             uniqEdgeOfSurfs.end());
   16032             : 
   16033             :         // Intersect with unique vertices as much as needed
   16034         796 :         bool insertedVertext = true;
   16035        2507 :         while (insertedVertext) {
   16036        1711 :             insertedVertext = false;
   16037             : 
   16038       40367 :             for (auto &edge : uniqEdgeOfSurfs) {
   16039             : 
   16040             :                 // now go through all the vertices and see if they are colinear with start and end vertices
   16041     6155768 :                 for (const auto &testVertex : uniqueRoofVertices) {
   16042     6117112 :                     if (edge.containsPoints(testVertex)) {
   16043         915 :                         SurfaceGeometry::EdgeOfSurf newEdgeOfSurface;
   16044         915 :                         newEdgeOfSurface.start = testVertex;
   16045         915 :                         newEdgeOfSurface.end = edge.end;
   16046         915 :                         edge.end = testVertex;
   16047         915 :                         uniqEdgeOfSurfs.emplace_back(std::move(newEdgeOfSurface));
   16048         915 :                         insertedVertext = true;
   16049         915 :                         break;
   16050         915 :                     }
   16051       39571 :                 }
   16052             :                 // Break out of the loop on edges, and start again at the while
   16053       39571 :                 if (insertedVertext) {
   16054         915 :                     break;
   16055             :                 }
   16056        1711 :             }
   16057             :         }
   16058             : 
   16059             :         // recount
   16060       10087 :         for (auto &edge : uniqEdgeOfSurfs) {
   16061        9291 :             edge.count = std::count(uniqEdgeOfSurfs.begin(), uniqEdgeOfSurfs.end(), edge);
   16062         796 :         }
   16063             : 
   16064        1592 :         uniqEdgeOfSurfs.erase(
   16065       10883 :             std::remove_if(uniqEdgeOfSurfs.begin(), uniqEdgeOfSurfs.end(), [](const auto &edge) -> bool { return edge.count == 2; }),
   16066        1592 :             uniqEdgeOfSurfs.end());
   16067             : 
   16068         796 :         geoSummaryRoof.Perimeter =
   16069         796 :             std::accumulate(uniqEdgeOfSurfs.cbegin(), uniqEdgeOfSurfs.cend(), 0.0, [](const double &sum, const SurfaceGeometry::EdgeOfSurf &edge) {
   16070        7155 :                 return sum + edge.length();
   16071             :             });
   16072         796 :     }
   16073             : 
   16074             : } // namespace SurfaceGeometry
   16075             : 
   16076             : } // namespace EnergyPlus

Generated by: LCOV version 1.14