LCOV - code coverage report
Current view: top level - EnergyPlus - HeatBalanceManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 71.7 % 3276 2348
Test Date: 2025-06-02 07:23:51 Functions: 97.1 % 35 34

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <algorithm>
      50              : #include <cmath>
      51              : #include <string>
      52              : 
      53              : // ObjexxFCL Headers
      54              : #include <ObjexxFCL/Array.functions.hh>
      55              : #include <ObjexxFCL/Array1S.hh>
      56              : #include <ObjexxFCL/ArrayS.functions.hh>
      57              : #include <ObjexxFCL/Fmath.hh>
      58              : #include <ObjexxFCL/string.functions.hh>
      59              : 
      60              : // EnergyPlus Headers
      61              : #include <EnergyPlus/Construction.hh>
      62              : #include <EnergyPlus/CurveManager.hh>
      63              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      64              : #include <EnergyPlus/DataBSDFWindow.hh>
      65              : #include <EnergyPlus/DataContaminantBalance.hh>
      66              : #include <EnergyPlus/DataHVACGlobals.hh>
      67              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      68              : #include <EnergyPlus/DataHeatBalSurface.hh>
      69              : #include <EnergyPlus/DataHeatBalance.hh>
      70              : #include <EnergyPlus/DataIPShortCuts.hh>
      71              : #include <EnergyPlus/DataReportingFlags.hh>
      72              : #include <EnergyPlus/DataStringGlobals.hh>
      73              : #include <EnergyPlus/DataSurfaces.hh>
      74              : #include <EnergyPlus/DataSystemVariables.hh>
      75              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      76              : #include <EnergyPlus/DaylightingDevices.hh>
      77              : #include <EnergyPlus/DaylightingManager.hh>
      78              : #include <EnergyPlus/DisplayRoutines.hh>
      79              : #include <EnergyPlus/EMSManager.hh>
      80              : #include <EnergyPlus/EconomicTariff.hh>
      81              : #include <EnergyPlus/FileSystem.hh>
      82              : #include <EnergyPlus/GlobalNames.hh>
      83              : #include <EnergyPlus/HVACSizingSimulationManager.hh>
      84              : #include <EnergyPlus/HVACSystemRootFindingAlgorithm.hh>
      85              : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
      86              : #include <EnergyPlus/HeatBalanceManager.hh>
      87              : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      88              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      89              : #include <EnergyPlus/InternalHeatGains.hh>
      90              : #include <EnergyPlus/Material.hh>
      91              : #include <EnergyPlus/MatrixDataManager.hh>
      92              : #include <EnergyPlus/NodeInputManager.hh>
      93              : #include <EnergyPlus/OutAirNodeManager.hh>
      94              : #include <EnergyPlus/OutputProcessor.hh>
      95              : #include <EnergyPlus/OutputReportTabular.hh>
      96              : #include <EnergyPlus/PhaseChangeModeling/HysteresisModel.hh>
      97              : #include <EnergyPlus/PluginManager.hh>
      98              : #include <EnergyPlus/ScheduleManager.hh>
      99              : #include <EnergyPlus/SolarShading.hh>
     100              : #include <EnergyPlus/StringUtilities.hh>
     101              : #include <EnergyPlus/SurfaceGeometry.hh>
     102              : #include <EnergyPlus/SurfaceOctree.hh>
     103              : #include <EnergyPlus/TARCOGGassesParams.hh>
     104              : #include <EnergyPlus/TARCOGParams.hh>
     105              : #include <EnergyPlus/UtilityRoutines.hh>
     106              : #include <EnergyPlus/WindowComplexManager.hh>
     107              : #include <EnergyPlus/WindowEquivalentLayer.hh>
     108              : #include <EnergyPlus/WindowManager.hh>
     109              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
     110              : 
     111              : namespace EnergyPlus {
     112              : 
     113              : namespace HeatBalanceManager {
     114              : 
     115              :     // Module containing the heat balance simulation routines
     116              :     // calculation (initialization) routines
     117              : 
     118              :     // MODULE INFORMATION:
     119              :     //       AUTHOR         Richard J. Liesen
     120              :     //       DATE WRITTEN   February 1998
     121              :     //       MODIFIED       November 1998, FW
     122              :     //       MODIFIED       April 1999, LKL
     123              :     //       MODIFIED       Dec 2006 DJS of PSU for ecoroof
     124              :     //       Added          Dec 2008 TH for thermochromic windows:
     125              :     //                       new subroutine CreateTCConstructions called by GetHeatBalanceInput
     126              : 
     127              :     // PURPOSE OF THIS MODULE:
     128              :     // To encapsulate the data and algorithms required to
     129              :     // manage the heat balance simulation on the building.
     130              : 
     131              :     // REFERENCES:
     132              :     // The heat balance method is outlined in the "Tarp Algorithms Manual"
     133              :     // The methods are also summarized in many BSO Theses and papers.
     134              : 
     135              :     // OTHER NOTES:
     136              :     // This module was created from IBLAST subroutines
     137              : 
     138              :     Array1D_string const PassFail(2, {"Fail", "Pass"});
     139              : 
     140      2828212 :     void ManageHeatBalance(EnergyPlusData &state)
     141              :     {
     142              : 
     143              :         // SUBROUTINE INFORMATION:
     144              :         //       AUTHOR         Rick Strand
     145              :         //       DATE WRITTEN   January 1997
     146              :         //       MODIFIED       February 1998 Richard Liesen
     147              : 
     148              :         // PURPOSE OF THIS SUBROUTINE:
     149              :         // This subroutine manages the heat balance method of calculating
     150              :         // building thermal loads.  It is called from the SimulationManager
     151              :         // at the time step level.  This driver manages the calls to all of
     152              :         // the other modules, drivers, and simulation algorithms.
     153              : 
     154              :         // METHODOLOGY EMPLOYED:
     155              :         // The order of this routine was taken from HeatBalanceModule with routine
     156              :         //  and Data Structuring
     157              : 
     158              :         // REFERENCES:
     159              :         // Legacy code from (I)BLAST, subroutine SIMZGD.
     160              : 
     161              :         // Using/Aliasing
     162              :         using namespace HeatBalanceSurfaceManager;
     163              :         using EMSManager::ManageEMS;
     164              :         using EMSManager::UpdateEMSTrendVariables;
     165              : 
     166              :         // Get the heat balance input at the beginning of the simulation only
     167      2828212 :         if (state.dataHeatBalMgr->ManageHeatBalanceGetInputFlag) {
     168          801 :             GetHeatBalanceInput(state); // Obtains heat balance related parameters from input file
     169          801 :             if (state.dataGlobal->DoingSizing) {
     170          428 :                 state.dataHeatBal->doSpaceHeatBalance = state.dataHeatBal->doSpaceHeatBalanceSizing;
     171              :             }
     172              : 
     173              :             // Surface octree setup
     174              :             //  The surface octree holds live references to surfaces so it must be updated
     175              :             //   if in the future surfaces are altered after this point
     176          801 :             if (state.dataSurface->TotSurfaces >= Dayltg::octreeCrossover) {                                            // Octree can be active
     177           93 :                 if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Daylighting:Controls") > 0) { // Daylighting is active
     178           16 :                     state.dataHeatBalMgr->surfaceOctree.init(state.dataSurface->Surface);                               // Set up surface octree
     179              :                 }
     180              :             }
     181              : 
     182        48091 :             for (auto &surface : state.dataSurface->Surface) {
     183        47290 :                 surface.set_computed_geometry(); // Set up extra surface geometry info for PierceSurface
     184          801 :             }
     185              : 
     186          801 :             state.dataHeatBalMgr->ManageHeatBalanceGetInputFlag = false;
     187              :         }
     188              : 
     189              :         bool anyRan;
     190              : 
     191      2828212 :         ManageEMS(state,
     192              :                   EMSManager::EMSCallFrom::BeginZoneTimestepBeforeInitHeatBalance,
     193              :                   anyRan,
     194      5656424 :                   ObjexxFCL::Optional_int_const()); // EMS calling point
     195              : 
     196              :         // These Inits will still have to be looked at as the routines are re-engineered further
     197              : 
     198      2828212 :         InitHeatBalance(state); // Initialize all heat balance related parameters
     199      2828212 :         ManageEMS(
     200      5656424 :             state, EMSManager::EMSCallFrom::BeginZoneTimestepAfterInitHeatBalance, anyRan, ObjexxFCL::Optional_int_const()); // EMS calling point
     201              : 
     202              :         // Solve the zone heat balance by first calling the Surface Heat Balance Manager
     203              :         // and then the Air Heat Balance Manager is called by the Surface Heat Balance
     204              :         // Manager.  The order of execution is still important and the zone cannot
     205              :         // go through any record keeping before the HVAC system has run because there
     206              :         // may be a radiant system in the building which will require iteration between
     207              :         // the HVAC system (called from the Air Heat Balance) and the zone (simulated
     208              :         // in the Surface Heat Balance Manager).  In the future, this may be improved.
     209      2828212 :         ManageSurfaceHeatBalance(state);
     210      2828213 :         ManageEMS(state, EMSManager::EMSCallFrom::EndZoneTimestepBeforeZoneReporting, anyRan, ObjexxFCL::Optional_int_const()); // EMS calling point
     211      2828211 :         RecKeepHeatBalance(state); // Do any heat balance related record keeping
     212              : 
     213              :         // This call has been moved to the FanSystemModule and does effect the output file
     214              :         //   You do get a shift in the Air Handling System Summary for the building electric loads
     215              :         // IF ((.NOT.WarmupFlag).AND.(DayOfSim.GT.0)) CALL RCKEEP  ! Do fan system accounting (to be moved later)
     216              : 
     217      2828211 :         ReportHeatBalance(state); // Manage heat balance reporting until the new reporting is in place
     218              : 
     219      2828211 :         ManageEMS(state, EMSManager::EMSCallFrom::EndZoneTimestepAfterZoneReporting, anyRan, ObjexxFCL::Optional_int_const()); // EMS calling point
     220              : 
     221      2828211 :         UpdateEMSTrendVariables(state);
     222      2828211 :         EnergyPlus::PluginManagement::PluginManager::updatePluginValues(state);
     223              : 
     224      2828211 :         if (state.dataGlobal->WarmupFlag && state.dataGlobal->EndDayFlag) {
     225              : 
     226        16827 :             CheckWarmupConvergence(state);
     227        16827 :             if (!state.dataGlobal->WarmupFlag) {
     228         2646 :                 state.dataGlobal->DayOfSim = 0; // Reset DayOfSim if Warmup converged
     229         2646 :                 state.dataGlobal->DayOfSimChr = "0";
     230              : 
     231         2646 :                 ManageEMS(state, EMSManager::EMSCallFrom::BeginNewEnvironmentAfterWarmUp, anyRan, ObjexxFCL::Optional_int_const()); // calling point
     232              :             }
     233              :         }
     234              : 
     235      2828211 :         if (!state.dataGlobal->WarmupFlag && state.dataGlobal->EndDayFlag && state.dataGlobal->DayOfSim == 1 && !state.dataGlobal->DoingSizing) {
     236         1706 :             ReportWarmupConvergence(state);
     237              :         }
     238      2828211 :     }
     239              : 
     240              :     // Get Input Section of the Module
     241              :     //******************************************************************************
     242              : 
     243          801 :     void GetHeatBalanceInput(EnergyPlusData &state)
     244              :     {
     245              : 
     246              :         // SUBROUTINE INFORMATION:
     247              :         //       AUTHOR         Rick Strand
     248              :         //       DATE WRITTEN   September 1997
     249              :         //       MODIFIED       February 1998 Richard Liesen
     250              :         //                      November 1998 FW
     251              : 
     252              :         // PURPOSE OF THIS SUBROUTINE:
     253              :         // This subroutine is the main driver for initializations within the
     254              :         // heat balance.
     255              : 
     256              :         // Using/Aliasing
     257              :         using InternalHeatGains::ManageInternalHeatGains;
     258              : 
     259              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     260          801 :         bool ErrorsFound(false); // If errors detected in input
     261              : 
     262          801 :         GetProjectControlData(state, ErrorsFound);
     263              : 
     264          801 :         GetSiteAtmosphereData(state, ErrorsFound);
     265              : 
     266          801 :         Material::GetWindowGlassSpectralData(state, ErrorsFound);
     267              : 
     268          801 :         Material::GetMaterialData(state, ErrorsFound); // Read materials from input file/transfer from legacy data structure
     269              : 
     270          801 :         Material::GetHysteresisData(state, ErrorsFound);
     271              : 
     272          801 :         GetFrameAndDividerData(state);
     273              : 
     274          801 :         GetConstructData(state, ErrorsFound); // Read constructs from input file/transfer from legacy data structure
     275              : 
     276          801 :         GetBuildingData(state, ErrorsFound); // Read building data from input file
     277              : 
     278          801 :         DataSurfaces::GetVariableAbsorptanceSurfaceList(state);
     279              : 
     280          801 :         GetIncidentSolarMultiplier(state, ErrorsFound);
     281              : 
     282              :         // Added SV 6/26/2013 to load scheduled surface gains
     283          801 :         GetScheduledSurfaceGains(state, ErrorsFound);
     284              : 
     285          801 :         if (state.dataSurface->UseRepresentativeSurfaceCalculations) {
     286            1 :             print(state.files.eio, "{}\n", "! <Representative Surface Assignment>,Surface Name,Representative Surface Name");
     287          580 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     288          579 :                 int RepSurfNum = state.dataSurface->Surface(SurfNum).RepresentativeCalcSurfNum;
     289          579 :                 if (SurfNum != RepSurfNum) {
     290          131 :                     print(state.files.eio,
     291              :                           " Representative Surface Assignment,{},{}\n",
     292          131 :                           state.dataSurface->Surface(SurfNum).Name,
     293          131 :                           state.dataSurface->Surface(RepSurfNum).Name);
     294              :                 }
     295              :             }
     296              :         }
     297              : 
     298              :         // Added TH 1/9/2009 to create thermochromic window constructions
     299          801 :         CreateTCConstructions(state, ErrorsFound);
     300              : 
     301          801 :         if (state.dataSurface->TotSurfaces > 0 && state.dataGlobal->NumOfZones == 0) {
     302            1 :             bool ValidSimulationWithNoZones = CheckValidSimulationObjects(state);
     303            1 :             if (!ValidSimulationWithNoZones) {
     304            0 :                 ShowSevereError(state, "GetHeatBalanceInput: There are surfaces in input but no zones found.  Invalid simulation.");
     305            0 :                 ErrorsFound = true;
     306              :             }
     307              :         }
     308              : 
     309          801 :         CheckUsedConstructions(state, ErrorsFound);
     310              : 
     311          801 :         if (ErrorsFound) {
     312            0 :             ShowFatalError(state, "Errors found in Building Input, Program Stopped");
     313              :         }
     314              : 
     315              :         // Set up enclosures before processing internal gains input
     316          801 :         HeatBalanceIntRadExchange::InitSolarViewFactors(state);
     317              : 
     318              :         // following is done to "get internal heat gains" input so that lights are gotten before
     319              :         // daylighting input
     320          801 :         ManageInternalHeatGains(state, true);
     321              : 
     322              :         // following is done so that people are gotten before for thermal comfort calculations
     323              :         // Setup Kiva instances
     324          801 :         if (state.dataHeatBal->AnyKiva) {
     325           10 :             state.dataSurfaceGeometry->kivaManager.setupKivaInstances(state);
     326              :         }
     327          801 :     }
     328              : 
     329          801 :     void CheckUsedConstructions(EnergyPlusData &state, [[maybe_unused]] bool &ErrorsFound)
     330              :     {
     331              : 
     332              :         // SUBROUTINE INFORMATION:
     333              :         //       AUTHOR         Linda Lawrie
     334              :         //       DATE WRITTEN   August 2011
     335              : 
     336              :         // PURPOSE OF THIS SUBROUTINE:
     337              :         // Counts or details unused constructions.
     338              : 
     339              :         // SUBROUTINE PARAMETER DEFINITIONS:
     340          801 :         int constexpr NumConstrObjects(6);
     341              :         Array1D_string const ConstrObjects(NumConstrObjects,
     342              :                                            {"Pipe:Indoor",
     343              :                                             "Pipe:Outdoor",
     344              :                                             "Pipe:Underground",
     345              :                                             "GroundHeatExchanger:Surface",
     346              :                                             "DaylightingDevice:Tubular",
     347          801 :                                             "EnergyManagementSystem:ConstructionIndexVariable"});
     348              : 
     349              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     350              :         int NumAlphas;
     351              :         int NumNumbers;
     352              :         int Status;
     353              :         int CNum;
     354              : 
     355              :         // Needs to account for Pipe:HeatTransfer/indoor, etc constructions.
     356         5607 :         for (int ONum = 1; ONum <= NumConstrObjects; ++ONum) {
     357         4806 :             int NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ConstrObjects(ONum));
     358         4832 :             for (int Loop = 1; Loop <= NumObjects; ++Loop) {
     359           52 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     360           26 :                                                                          ConstrObjects(ONum),
     361              :                                                                          Loop,
     362           26 :                                                                          state.dataIPShortCut->cAlphaArgs,
     363              :                                                                          NumAlphas,
     364           26 :                                                                          state.dataIPShortCut->rNumericArgs,
     365              :                                                                          NumNumbers,
     366              :                                                                          Status);
     367           26 :                 if (ONum == 5) {
     368            2 :                     CNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataConstruction->Construct);
     369              :                 } else {
     370           24 :                     CNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct);
     371              :                 }
     372           26 :                 if (CNum == 0) {
     373            0 :                     continue;
     374              :                 }
     375           26 :                 state.dataConstruction->Construct(CNum).IsUsed = true;
     376           26 :                 if (ONum == 4 || ONum == 6) {
     377              :                     // GroundHeatExchanger:Surface or EnergyManagementSystem:ConstructionIndexVariable
     378              :                     // Include all EMS constructions since they can potentially be used by a CTF surface
     379           20 :                     if (!state.dataConstruction->Construct(CNum).TypeIsWindow) {
     380            1 :                         state.dataConstruction->Construct(CNum).IsUsedCTF = true;
     381              :                     }
     382              :                 }
     383              :             }
     384              :         }
     385         1602 :         int Unused = state.dataHeatBal->TotConstructs - std::count_if(state.dataConstruction->Construct.begin(),
     386          801 :                                                                       state.dataConstruction->Construct.end(),
     387         6105 :                                                                       [](Construction::ConstructionProps const &e) { return e.IsUsed; });
     388          801 :         if (Unused > 0) {
     389           29 :             if (!state.dataGlobal->DisplayExtraWarnings) {
     390           28 :                 ShowWarningError(state, format("CheckUsedConstructions: There are {} nominally unused constructions in input.", Unused));
     391           84 :                 ShowContinueError(state, "For explicit details on each unused construction, use Output:Diagnostics,DisplayExtraWarnings;");
     392              :             } else {
     393            1 :                 ShowWarningError(state, format("CheckUsedConstructions: There are {} nominally unused constructions in input.", Unused));
     394            2 :                 ShowContinueError(state, "Each Unused construction is shown.");
     395           12 :                 for (int Loop = 1; Loop <= state.dataHeatBal->TotConstructs; ++Loop) {
     396           11 :                     if (state.dataConstruction->Construct(Loop).IsUsed) {
     397           10 :                         continue;
     398              :                     }
     399            1 :                     ShowMessage(state, format("Construction={}", state.dataConstruction->Construct(Loop).Name));
     400              :                 }
     401              :             }
     402              :         }
     403          801 :     }
     404              : 
     405            1 :     bool CheckValidSimulationObjects(EnergyPlusData &state)
     406              :     {
     407              : 
     408              :         // FUNCTION INFORMATION:
     409              :         //       AUTHOR         Linda Lawrie
     410              :         //       DATE WRITTEN   July 2008
     411              : 
     412              :         // PURPOSE OF THIS FUNCTION:
     413              :         // If an input file presents with surfaces but no zones, there are certain objects
     414              :         // that must be present for the simulation to be valid.  This check was necessitated by
     415              :         // an input file that was entirely detached shading surfaces but no zones (and nothing else).
     416              :         // Other objects include Solar Collectors, PV arrays.
     417              : 
     418              :         // METHODOLOGY EMPLOYED:
     419              :         // Check for specific objects that must be present for such a simulation to be valid.
     420              : 
     421              :         // Return value
     422              :         bool ValidSimulation; // True is other objects appear to make this a valid simulation.
     423              : 
     424            1 :         ValidSimulation = false;
     425            1 :         if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SolarCollector:FlatPlate:Water") > 0) {
     426            1 :             ValidSimulation = true;
     427            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:Photovoltaic") > 0) {
     428            0 :             ValidSimulation = true;
     429            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:InternalCombustionEngine") > 0) {
     430            0 :             ValidSimulation = true;
     431            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:CombustionTurbine") > 0) {
     432            0 :             ValidSimulation = true;
     433            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:FuelCell") > 0) {
     434            0 :             ValidSimulation = true;
     435            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:MicroCHP") > 0) {
     436            0 :             ValidSimulation = true;
     437            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:MicroTurbine") > 0) {
     438            0 :             ValidSimulation = true;
     439            0 :         } else if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Generator:WindTurbine") > 0) {
     440            0 :             ValidSimulation = true;
     441              :         }
     442              : 
     443            1 :         return ValidSimulation;
     444              :     }
     445              : 
     446          801 :     void SetPreConstructionInputParameters(EnergyPlusData &state)
     447              :     {
     448              :         // SUBROUTINE INFORMATION:
     449              :         //       AUTHOR         Edwin Lee
     450              :         //       DATE WRITTEN   October 2014
     451              : 
     452              :         // PURPOSE OF THIS SUBROUTINE:
     453              :         // This subroutine sets parameters that need to be established before any heat balance inputs are read
     454              : 
     455              :         int NumAlpha;
     456              :         int NumNumber;
     457              :         int IOStat;
     458              : 
     459              :         // Get all the construction objects to determine the max layers and use this as the value for DataHeatBalance::MaxSolidWinLayers
     460              :         // The variable MaxSolidWinLayers is initialized to zero to immediately catch any issues with timing of this routine
     461              : 
     462              :         // start by setting this to 5; it will satisfy the regular window constructions (Construction) and the Window5 files
     463              :         // (Construction:WindowDataFile)
     464          801 :         state.dataHeatBal->MaxSolidWinLayers = 7;
     465              : 
     466              :         // Construction:ComplexFenestrationState have a limit of 10 layers, so set it up to 10 if they are present
     467          801 :         if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:ComplexFenestrationState") > 0) {
     468           10 :             state.dataHeatBal->MaxSolidWinLayers = max(state.dataHeatBal->MaxSolidWinLayers, 10);
     469              :         }
     470              : 
     471              :         // then process the rest of the relevant constructions
     472          801 :         std::string constructName("Construction:WindowEquivalentLayer");
     473          801 :         int numConstructions(state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, constructName));
     474          804 :         for (int constructionNum = 1; constructionNum <= numConstructions; ++constructionNum) {
     475            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     476              :                                                                      constructName,
     477              :                                                                      constructionNum,
     478            3 :                                                                      state.dataIPShortCut->cAlphaArgs,
     479              :                                                                      NumAlpha,
     480            3 :                                                                      state.dataIPShortCut->rNumericArgs,
     481              :                                                                      NumNumber,
     482              :                                                                      IOStat,
     483            3 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     484            3 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     485            3 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     486            3 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     487            3 :             int numLayersInThisConstruct(NumAlpha - 1);
     488            3 :             state.dataHeatBal->MaxSolidWinLayers = max(state.dataHeatBal->MaxSolidWinLayers, numLayersInThisConstruct);
     489              :         }
     490              : 
     491              :         // construction types being ignored as they are opaque: Construction:CfactorUndergroundWall, Construction:FfactorGroundFloor,
     492          801 :     }
     493              : 
     494          801 :     void GetProjectControlData(EnergyPlusData &state, bool &ErrorsFound) // Set to true if errors detected during getting data
     495              :     {
     496              : 
     497              :         // SUBROUTINE INFORMATION:
     498              :         //       AUTHOR         Linda Lawrie
     499              :         //       DATE WRITTEN   October 2004
     500              : 
     501              :         // PURPOSE OF THIS SUBROUTINE:
     502              :         // This subroutine gets the project control data before the rest of the building data (such as
     503              :         // materials) is obtained.
     504              : 
     505              :         // REFERENCES:
     506              :         // This routine gets the following objects:
     507              :         // BUILDING
     508              :         // INSIDE CONVECTION ALGORITHM
     509              :         // OUTSIDE CONVECTION ALGORITHM
     510              :         // SOLUTION ALGORITHM
     511              :         // ASHRAE Handbook of Fundamentals, Chap 16, for the setting of Site Atmospheric defaults based
     512              :         //   on terrain.
     513              :         // ZoneAirHeatBalanceAlgorithm, Added by L. Gu, 12/09
     514              :         // ZoneAirContaminantBalance, Added by L. Gu, 06/10
     515              : 
     516              :         // Using/Aliasing
     517          801 :         auto &HVACSystemRootFinding = state.dataRootFinder->HVACSystemRootFinding;
     518              : 
     519              :         // SUBROUTINE PARAMETER DEFINITIONS:
     520              :         static constexpr std::string_view RoutineName("GetProjectControlData: ");
     521              :         static constexpr std::string_view routineName = "GetProjectControlData";
     522              : 
     523              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     524          801 :         Array1D_string AlphaName(4);
     525          801 :         Array1D<Real64> BuildingNumbers(5);
     526              :         int NumAlpha;
     527              :         int NumNumber;
     528              :         int IOStat;
     529              :         std::string::size_type TMP;
     530              : 
     531              :         // Assign the values to the building data
     532              : 
     533          801 :         state.dataHeatBalMgr->CurrentModuleObject = "Building";
     534          801 :         int NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     535              : 
     536          801 :         if (NumObjects > 0) {
     537         2403 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     538          801 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
     539              :                                                                      1,
     540              :                                                                      AlphaName,
     541              :                                                                      NumAlpha,
     542              :                                                                      BuildingNumbers,
     543              :                                                                      NumNumber,
     544              :                                                                      IOStat,
     545          801 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     546          801 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     547          801 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     548          801 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     549              :             // Building Name (remove certain characters)
     550          801 :             state.dataHeatBal->BuildingName = AlphaName(1);
     551          801 :             TMP = index(state.dataHeatBal->BuildingName, char(1));
     552          801 :             while (TMP != std::string::npos) {
     553            0 :                 state.dataHeatBal->BuildingName[TMP] = ',';
     554            0 :                 TMP = index(state.dataHeatBal->BuildingName, char(1));
     555              :             }
     556          801 :             TMP = index(state.dataHeatBal->BuildingName, char(2));
     557          801 :             while (TMP != std::string::npos) {
     558            0 :                 state.dataHeatBal->BuildingName[TMP] = '!';
     559            0 :                 TMP = index(state.dataHeatBal->BuildingName, char(2));
     560              :             }
     561          801 :             TMP = index(state.dataHeatBal->BuildingName, char(3));
     562          801 :             while (TMP != std::string::npos) {
     563            0 :                 state.dataHeatBal->BuildingName[TMP] = '\\';
     564            0 :                 TMP = index(state.dataHeatBal->BuildingName, char(3));
     565              :             }
     566              :             // Building Azimuth (no validation)
     567          801 :             state.dataHeatBal->BuildingAzimuth = mod(BuildingNumbers(1), 360.0);
     568              :             // Terrain
     569          801 :             if (AlphaName(2) == "COUNTRY" || AlphaName(2) == "1") {
     570           10 :                 state.dataEnvrn->SiteWindExp = 0.14;
     571           10 :                 state.dataEnvrn->SiteWindBLHeight = 270.0;
     572           10 :                 AlphaName(2) = "Country";
     573          791 :             } else if (AlphaName(2) == "SUBURBS" || AlphaName(2) == "2" || AlphaName(2) == "SUBURB") {
     574          450 :                 state.dataEnvrn->SiteWindExp = 0.22;
     575          450 :                 state.dataEnvrn->SiteWindBLHeight = 370.0;
     576          450 :                 AlphaName(2) = "Suburbs";
     577          341 :             } else if (AlphaName(2) == "CITY" || AlphaName(2) == "3") {
     578          339 :                 state.dataEnvrn->SiteWindExp = 0.33;
     579          339 :                 state.dataEnvrn->SiteWindBLHeight = 460.0;
     580          339 :                 AlphaName(2) = "City";
     581            2 :             } else if (AlphaName(2) == "OCEAN") {
     582            0 :                 state.dataEnvrn->SiteWindExp = 0.10;
     583            0 :                 state.dataEnvrn->SiteWindBLHeight = 210.0;
     584            0 :                 AlphaName(2) = "Ocean";
     585            2 :             } else if (AlphaName(2) == "URBAN") {
     586            2 :                 state.dataEnvrn->SiteWindExp = 0.22;
     587            2 :                 state.dataEnvrn->SiteWindBLHeight = 370.0;
     588            2 :                 AlphaName(2) = "Urban";
     589              :             } else {
     590            0 :                 ShowSevereError(state,
     591            0 :                                 format("{}{}: {} invalid={}",
     592              :                                        RoutineName,
     593            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
     594            0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
     595              :                                        AlphaName(2)));
     596            0 :                 state.dataEnvrn->SiteWindExp = 0.14;
     597            0 :                 state.dataEnvrn->SiteWindBLHeight = 270.0;
     598            0 :                 AlphaName(2) = AlphaName(2) + "-invalid";
     599            0 :                 ErrorsFound = true;
     600              :             }
     601              :             // Loads Convergence Tolerance Value
     602          801 :             state.dataHeatBal->LoadsConvergTol = BuildingNumbers(2);
     603          801 :             if (state.dataHeatBal->LoadsConvergTol <= 0.0) {
     604            0 :                 ShowSevereError(state,
     605            0 :                                 format("{}{}: {} value invalid, [{:.3R}]",
     606              :                                        RoutineName,
     607            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
     608            0 :                                        state.dataIPShortCut->cNumericFieldNames(2),
     609            0 :                                        state.dataHeatBal->LoadsConvergTol));
     610            0 :                 ErrorsFound = true;
     611              :             }
     612              :             // Temperature Convergence Tolerance Value
     613          801 :             state.dataHeatBal->TempConvergTol = BuildingNumbers(3);
     614          801 :             if (state.dataHeatBal->TempConvergTol <= 0.0) {
     615            0 :                 ShowSevereError(state,
     616            0 :                                 format("{}{}: {} value invalid, [{:.3R}]",
     617              :                                        RoutineName,
     618            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
     619            0 :                                        state.dataIPShortCut->cNumericFieldNames(3),
     620            0 :                                        state.dataHeatBal->TempConvergTol));
     621            0 :                 ErrorsFound = true;
     622              :             }
     623              :             // Solar Distribution
     624          801 :             if (has_prefix(AlphaName(3), "MIN") || AlphaName(3) == "-1" || state.dataSysVars->lMinimalShadowing) {
     625          104 :                 state.dataHeatBal->SolarDistribution = DataHeatBalance::Shadowing::Minimal;
     626          104 :                 AlphaName(3) = "MinimalShadowing";
     627          104 :                 state.dataSurface->CalcSolRefl = false;
     628          697 :             } else if (AlphaName(3) == "FULLEXTERIOR" || AlphaName(3) == "0") {
     629          242 :                 state.dataHeatBal->SolarDistribution = DataHeatBalance::Shadowing::FullExterior;
     630          242 :                 AlphaName(3) = "FullExterior";
     631          242 :                 state.dataSurface->CalcSolRefl = false;
     632          455 :             } else if (AlphaName(3) == "FULLINTERIORANDEXTERIOR" || AlphaName(3) == "1") {
     633          446 :                 state.dataHeatBal->SolarDistribution = DataHeatBalance::Shadowing::FullInteriorExterior;
     634          446 :                 AlphaName(3) = "FullInteriorAndExterior";
     635          446 :                 state.dataSurface->CalcSolRefl = false;
     636            9 :             } else if (AlphaName(3) == "FULLEXTERIORWITHREFLECTIONS") {
     637            3 :                 state.dataHeatBal->SolarDistribution = DataHeatBalance::Shadowing::FullExterior;
     638            3 :                 AlphaName(3) = "FullExteriorWithReflectionsFromExteriorSurfaces";
     639            3 :                 state.dataSurface->CalcSolRefl = true;
     640            6 :             } else if (AlphaName(3) == "FULLINTERIORANDEXTERIORWITHREFLECTIONS") {
     641            6 :                 state.dataHeatBal->SolarDistribution = DataHeatBalance::Shadowing::FullInteriorExterior;
     642            6 :                 AlphaName(3) = "FullInteriorAndExteriorWithReflectionsFromExteriorSurfaces";
     643            6 :                 state.dataSurface->CalcSolRefl = true;
     644              :             } else {
     645            0 :                 ShowSevereError(state,
     646            0 :                                 format("{}{}: {} invalid={}",
     647              :                                        RoutineName,
     648            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
     649            0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     650              :                                        AlphaName(3)));
     651            0 :                 ErrorsFound = true;
     652            0 :                 AlphaName(3) = AlphaName(3) + "-invalid";
     653              :             }
     654              :             // Maximum Number of Warmup Days
     655          801 :             if (!state.dataIPShortCut->lNumericFieldBlanks(4)) {
     656          780 :                 state.dataHeatBal->MaxNumberOfWarmupDays = BuildingNumbers(4);
     657          780 :                 if (state.dataHeatBal->MaxNumberOfWarmupDays <= 0) {
     658            0 :                     ShowSevereError(state,
     659            0 :                                     format("{}{}: {} invalid, [{}], {} will be used",
     660              :                                            RoutineName,
     661            0 :                                            state.dataHeatBalMgr->CurrentModuleObject,
     662            0 :                                            state.dataIPShortCut->cNumericFieldNames(4),
     663            0 :                                            state.dataHeatBal->MaxNumberOfWarmupDays,
     664              :                                            DataHeatBalance::DefaultMaxNumberOfWarmupDays));
     665            0 :                     state.dataHeatBal->MaxNumberOfWarmupDays = DataHeatBalance::DefaultMaxNumberOfWarmupDays;
     666              :                 }
     667              :             } else {
     668           21 :                 state.dataHeatBal->MaxNumberOfWarmupDays = DataHeatBalance::DefaultMaxNumberOfWarmupDays;
     669              :             }
     670              :             // Minimum Number of Warmup Days
     671          801 :             if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
     672          793 :                 state.dataHeatBal->MinNumberOfWarmupDays = BuildingNumbers(5);
     673          793 :                 if (state.dataHeatBal->MinNumberOfWarmupDays <= 0) {
     674            0 :                     ShowWarningError(state,
     675            0 :                                      format("{}{}: {} invalid, [{}], {} will be used",
     676              :                                             RoutineName,
     677            0 :                                             state.dataHeatBalMgr->CurrentModuleObject,
     678            0 :                                             state.dataIPShortCut->cNumericFieldNames(5),
     679            0 :                                             state.dataHeatBal->MinNumberOfWarmupDays,
     680              :                                             DataHeatBalance::DefaultMinNumberOfWarmupDays));
     681            0 :                     state.dataHeatBal->MinNumberOfWarmupDays = DataHeatBalance::DefaultMinNumberOfWarmupDays;
     682              :                 }
     683              :             } else {
     684            8 :                 state.dataHeatBal->MinNumberOfWarmupDays = DataHeatBalance::DefaultMinNumberOfWarmupDays;
     685              :             }
     686          801 :             if (state.dataHeatBal->MinNumberOfWarmupDays > state.dataHeatBal->MaxNumberOfWarmupDays) {
     687            0 :                 ShowWarningError(state,
     688            0 :                                  format("{}{}: {} [{}]  is greater than {} [{}], {} will be used.",
     689              :                                         RoutineName,
     690            0 :                                         state.dataHeatBalMgr->CurrentModuleObject,
     691            0 :                                         state.dataIPShortCut->cNumericFieldNames(5),
     692            0 :                                         state.dataHeatBal->MinNumberOfWarmupDays,
     693            0 :                                         state.dataIPShortCut->cNumericFieldNames(4),
     694            0 :                                         state.dataHeatBal->MaxNumberOfWarmupDays,
     695            0 :                                         state.dataHeatBal->MinNumberOfWarmupDays));
     696            0 :                 state.dataHeatBal->MaxNumberOfWarmupDays = state.dataHeatBal->MinNumberOfWarmupDays;
     697              :             }
     698              : 
     699              :         } else {
     700            0 :             ShowSevereError(state, format("{} A {} Object must be entered.", RoutineName, state.dataHeatBalMgr->CurrentModuleObject));
     701            0 :             ErrorsFound = true;
     702            0 :             state.dataHeatBal->BuildingName = "NOT ENTERED";
     703            0 :             AlphaName(2) = "NOT ENTERED";
     704            0 :             AlphaName(3) = "NOT ENTERED";
     705            0 :             state.dataHeatBal->MaxNumberOfWarmupDays = DataHeatBalance::DefaultMaxNumberOfWarmupDays;
     706            0 :             state.dataHeatBal->MinNumberOfWarmupDays = DataHeatBalance::DefaultMinNumberOfWarmupDays;
     707              :         }
     708              : 
     709          801 :         constexpr const char *Format_720(" Building Information,{},{:.3R},{},{:.5R},{:.5R},{},{},{}\n");
     710          801 :         constexpr const char *Format_721("! <Building Information>, Building Name,North Axis {{deg}},Terrain,  Loads Convergence Tolerance "
     711              :                                          "Value,Temperature Convergence Tolerance Value,  Solar Distribution,Maximum Number of Warmup Days,Minimum "
     712              :                                          "Number of Warmup Days\n");
     713              :         // Write Building Information to the initialization output file
     714          801 :         print(state.files.eio, Format_721);
     715          801 :         print(state.files.eio,
     716              :               Format_720,
     717          801 :               state.dataHeatBal->BuildingName,
     718          801 :               state.dataHeatBal->BuildingAzimuth,
     719              :               AlphaName(2),
     720          801 :               state.dataHeatBal->LoadsConvergTol,
     721          801 :               state.dataHeatBal->TempConvergTol,
     722              :               AlphaName(3),
     723          801 :               state.dataHeatBal->MaxNumberOfWarmupDays,
     724          801 :               state.dataHeatBal->MinNumberOfWarmupDays);
     725              :         // Above should be validated...
     726              : 
     727          801 :         state.dataHeatBalMgr->CurrentModuleObject = "SurfaceConvectionAlgorithm:Inside";
     728          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     729          801 :         if (NumObjects > 0) {
     730         2241 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     731          747 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
     732              :                                                                      1,
     733              :                                                                      AlphaName,
     734              :                                                                      NumAlpha,
     735              :                                                                      BuildingNumbers,
     736              :                                                                      NumNumber,
     737              :                                                                      IOStat,
     738          747 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     739          747 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     740          747 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     741          747 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     742              : 
     743          747 :             Convect::HcInt hcIn = static_cast<Convect::HcInt>(getEnumValue(Convect::HcIntNamesUC, AlphaName(1)));
     744              : 
     745          747 :             if (hcIn == Convect::HcInt::TrombeWall) {
     746            0 :                 ShowSevereError(state,
     747              :                                 "GetInsideConvectionAlgorithm: TrombeWall has been used as a global definition. This is a zone oriented value.  "
     748              :                                 "Will be illegal in the future.");
     749          747 :             } else if (hcIn != Convect::HcInt::ASHRAESimple && hcIn != Convect::HcInt::ASHRAETARP && hcIn != Convect::HcInt::CeilingDiffuser &&
     750            0 :                        hcIn != Convect::HcInt::AdaptiveConvectionAlgorithm && hcIn != Convect::HcInt::ASTMC1340) {
     751            0 :                 ShowWarningError(state,
     752            0 :                                  format("GetInsideConvectionAlgorithm: Invalid value for {}, defaulting to TARP, invalid value={}",
     753            0 :                                         state.dataHeatBalMgr->CurrentModuleObject,
     754              :                                         AlphaName(1)));
     755            0 :                 hcIn = Convect::HcInt::ASHRAETARP;
     756              :             }
     757          747 :             state.dataHeatBal->DefaultIntConvAlgo = hcIn;
     758              :         } else {
     759              :             // default value, if not specified
     760           54 :             state.dataHeatBal->DefaultIntConvAlgo = Convect::HcInt::ASHRAETARP;
     761              :         }
     762          801 :         constexpr const char *Format_722("! <Inside Convection Algorithm>, Algorithm {{Simple | TARP | CeilingDiffuser | "
     763              :                                          "AdaptiveConvectionAlgorithm}}\nInside Convection Algorithm,{}\n");
     764          801 :         print(state.files.eio, Format_722, Convect::HcIntNames[static_cast<int>(state.dataHeatBal->DefaultIntConvAlgo)]);
     765              : 
     766              :         // Get only the first (if more were input)
     767          801 :         state.dataHeatBalMgr->CurrentModuleObject = "SurfaceConvectionAlgorithm:Outside";
     768          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     769          801 :         if (NumObjects > 0) {
     770         1488 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     771              :                                                                      "SurfaceConvectionAlgorithm:Outside",
     772              :                                                                      1,
     773              :                                                                      AlphaName,
     774              :                                                                      NumAlpha,
     775              :                                                                      BuildingNumbers,
     776              :                                                                      NumNumber,
     777              :                                                                      IOStat,
     778          744 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     779          744 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     780          744 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     781          744 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     782              : 
     783          744 :             Convect::HcExt hcOut = static_cast<Convect::HcExt>(getEnumValue(Convect::HcExtNamesUC, AlphaName(1)));
     784              : 
     785          744 :             if (hcOut != Convect::HcExt::ASHRAESimple && hcOut != Convect::HcExt::ASHRAETARP && hcOut != Convect::HcExt::MoWiTTHcOutside &&
     786            3 :                 hcOut != Convect::HcExt::DOE2HcOutside && hcOut != Convect::HcExt::AdaptiveConvectionAlgorithm) {
     787            0 :                 ShowWarningError(state,
     788            0 :                                  format("GetOutsideConvectionAlgorithm: Invalid value for {}, defaulting to DOE-2, invalid value={}",
     789            0 :                                         state.dataHeatBalMgr->CurrentModuleObject,
     790              :                                         AlphaName(1)));
     791            0 :                 hcOut = Convect::HcExt::DOE2HcOutside;
     792              :             }
     793          744 :             state.dataHeatBal->DefaultExtConvAlgo = hcOut;
     794              :         } else {
     795              :             // default value, if not specified
     796           57 :             state.dataHeatBal->DefaultExtConvAlgo = Convect::HcExt::DOE2HcOutside;
     797              :         }
     798              : 
     799          801 :         constexpr const char *Format_723("! <Outside Convection Algorithm>, Algorithm {{SimpleCombined | TARP | MoWitt | DOE-2 | "
     800              :                                          "AdaptiveConvectionAlgorithm}}\nOutside Convection Algorithm,{}\n");
     801          801 :         print(state.files.eio, Format_723, Convect::HcExtNames[static_cast<int>(state.dataHeatBal->DefaultExtConvAlgo)]);
     802              : 
     803          801 :         state.dataHeatBalMgr->CurrentModuleObject = "HeatBalanceAlgorithm";
     804          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     805          801 :         if (NumObjects > 0) {
     806         2166 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     807          722 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
     808              :                                                                      1,
     809              :                                                                      AlphaName,
     810              :                                                                      NumAlpha,
     811              :                                                                      BuildingNumbers,
     812              :                                                                      NumNumber,
     813              :                                                                      IOStat,
     814          722 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     815          722 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     816          722 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     817          722 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     818              : 
     819              :             {
     820          722 :                 std::string const &SELECT_CASE_var = AlphaName(1);
     821              :                 // The default is CTF
     822          722 :                 if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
     823          708 :                     state.dataHeatBal->OverallHeatTransferSolutionAlgo = DataSurfaces::HeatTransferModel::CTF;
     824          708 :                     state.dataHeatBal->AnyCTF = true;
     825              : 
     826           14 :                 } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
     827            1 :                     state.dataHeatBal->OverallHeatTransferSolutionAlgo = DataSurfaces::HeatTransferModel::EMPD;
     828            1 :                     state.dataHeatBal->AnyEMPD = true;
     829            1 :                     state.dataHeatBal->AllCTF = false;
     830           13 :                 } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
     831           11 :                     state.dataHeatBal->OverallHeatTransferSolutionAlgo = DataSurfaces::HeatTransferModel::CondFD;
     832           11 :                     state.dataHeatBal->AnyCondFD = true;
     833           11 :                     state.dataHeatBal->AllCTF = false;
     834           11 :                     if (state.dataGlobal->TimeStepsInHour < 20) {
     835            0 :                         ShowSevereError(
     836              :                             state,
     837            0 :                             format("GetSolutionAlgorithm: {} {} is Conduction Finite Difference but Number of TimeSteps in Hour < 20, Value is {}.",
     838            0 :                                    state.dataHeatBalMgr->CurrentModuleObject,
     839            0 :                                    state.dataIPShortCut->cAlphaFieldNames(1),
     840            0 :                                    state.dataGlobal->TimeStepsInHour));
     841            0 :                         ShowContinueError(state,
     842              :                                           "...Suggested minimum number of time steps in hour for Conduction Finite Difference solutions is 20. "
     843              :                                           "Errors or inaccurate calculations may occur.");
     844              :                     }
     845              : 
     846            2 :                 } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
     847            2 :                     state.dataHeatBal->OverallHeatTransferSolutionAlgo = DataSurfaces::HeatTransferModel::HAMT;
     848            2 :                     state.dataHeatBal->AnyHAMT = true;
     849            2 :                     state.dataHeatBal->AllCTF = false;
     850            2 :                     if (state.dataGlobal->TimeStepsInHour < 20) {
     851            0 :                         ShowSevereError(state,
     852            0 :                                         format("GetSolutionAlgorithm: {} {} is Combined Heat and Moisture Finite Element but Number of TimeSteps in "
     853              :                                                "Hour < 20, Value is {}.",
     854            0 :                                                state.dataHeatBalMgr->CurrentModuleObject,
     855            0 :                                                state.dataIPShortCut->cAlphaFieldNames(1),
     856            0 :                                                state.dataGlobal->TimeStepsInHour));
     857            0 :                         ShowContinueError(state,
     858              :                                           "...Suggested minimum number of time steps in hour for Combined Heat and Moisture Finite Element solutions "
     859              :                                           "is 20. Errors or inaccurate calculations may occur.");
     860            0 :                         ShowContinueError(state,
     861              :                                           "...If the simulation crashes, look at material properties (esp porosity), use timestep=60, or less layers "
     862              :                                           "in your constructions.");
     863              :                     }
     864              : 
     865              :                 } else {
     866            0 :                     state.dataHeatBal->OverallHeatTransferSolutionAlgo = DataSurfaces::HeatTransferModel::CTF;
     867            0 :                     state.dataHeatBal->AnyCTF = true;
     868              :                 }
     869              :             }
     870              : 
     871          722 :             if (NumNumber > 0) {
     872           93 :                 state.dataHeatBalSurf->MaxSurfaceTempLimit = BuildingNumbers(1);
     873           93 :                 state.dataHeatBalSurf->MaxSurfaceTempLimitBeforeFatal = state.dataHeatBalSurf->MaxSurfaceTempLimit * 2.5;
     874           93 :                 if (state.dataHeatBalSurf->MaxSurfaceTempLimit < DataHeatBalSurface::MinSurfaceTempLimit) {
     875           93 :                 } else if (state.dataHeatBalSurf->MaxSurfaceTempLimit < 0.0) {
     876            0 :                     state.dataHeatBalSurf->MaxSurfaceTempLimit = DataHeatBalSurface::DefaultSurfaceTempLimit;
     877            0 :                     state.dataHeatBalSurf->MaxSurfaceTempLimitBeforeFatal = state.dataHeatBalSurf->MaxSurfaceTempLimit * 2.5;
     878              :                 }
     879              :             }
     880              : 
     881          722 :             if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
     882            0 :                 state.dataHeatBal->LowHConvLimit = BuildingNumbers(2);
     883              :             }
     884          722 :             if (!state.dataIPShortCut->lNumericFieldBlanks(3)) {
     885            0 :                 state.dataHeatBal->HighHConvLimit = BuildingNumbers(3);
     886              :             }
     887              : 
     888              :         } else {
     889           79 :             state.dataHeatBal->OverallHeatTransferSolutionAlgo = DataSurfaces::HeatTransferModel::CTF;
     890           79 :             state.dataHeatBal->AnyCTF = true;
     891           79 :             state.dataHeatBalSurf->MaxSurfaceTempLimit = DataHeatBalSurface::DefaultSurfaceTempLimit;
     892           79 :             state.dataHeatBalSurf->MaxSurfaceTempLimitBeforeFatal = state.dataHeatBalSurf->MaxSurfaceTempLimit * 2.5;
     893              :         }
     894              : 
     895              :         // algorithm input checks now deferred until surface properties are read in,
     896              :         //  moved to SurfaceGeometry.cc routine GetSurfaceHeatTransferAlgorithmOverrides
     897              : 
     898          801 :         constexpr const char *Format_724("! <Sky Radiance Distribution>, Value {{Anisotropic}}\nSky Radiance Distribution,Anisotropic\n");
     899          801 :         print(state.files.eio, Format_724);
     900              : 
     901          801 :         state.dataHeatBalMgr->CurrentModuleObject = "Compliance:Building";
     902          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     903              : 
     904          801 :         if (NumObjects > 0) {
     905           15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     906            5 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
     907              :                                                                      1,
     908              :                                                                      AlphaName,
     909              :                                                                      NumAlpha,
     910              :                                                                      BuildingNumbers,
     911              :                                                                      NumNumber,
     912              :                                                                      IOStat,
     913            5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     914            5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     915            5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     916            5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     917              :             // Building Rotation for Appendix G
     918            5 :             state.dataHeatBal->BuildingRotationAppendixG = mod(BuildingNumbers(1), 360.0);
     919              :         }
     920              : 
     921              :         // A new object is added by L. Gu, 12/09
     922          801 :         state.dataHeatBalMgr->CurrentModuleObject = "ZoneAirHeatBalanceAlgorithm";
     923          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     924          801 :         if (NumObjects > 0) {
     925          234 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     926           78 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
     927              :                                                                      1,
     928              :                                                                      AlphaName,
     929              :                                                                      NumAlpha,
     930              :                                                                      BuildingNumbers,
     931              :                                                                      NumNumber,
     932              :                                                                      IOStat,
     933           78 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     934           78 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     935           78 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     936           78 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     937           78 :             if (NumAlpha > 0) {
     938              :                 {
     939           78 :                     std::string const &SELECT_CASE_var = AlphaName(1);
     940           78 :                     if (SELECT_CASE_var == "THIRDORDERBACKWARDDIFFERENCE") {
     941            2 :                         state.dataHeatBal->ZoneAirSolutionAlgo = DataHeatBalance::SolutionAlgo::ThirdOrder;
     942            2 :                         AlphaName(1) = "ThirdOrderBackwardDifference";
     943           76 :                     } else if (SELECT_CASE_var == "ANALYTICALSOLUTION") {
     944           74 :                         state.dataHeatBal->ZoneAirSolutionAlgo = DataHeatBalance::SolutionAlgo::AnalyticalSolution;
     945           74 :                         AlphaName(1) = "AnalyticalSolution";
     946            2 :                     } else if (SELECT_CASE_var == "EULERMETHOD") {
     947            2 :                         state.dataHeatBal->ZoneAirSolutionAlgo = DataHeatBalance::SolutionAlgo::EulerMethod;
     948            2 :                         AlphaName(1) = "EulerMethod";
     949              :                     } else {
     950            0 :                         state.dataHeatBal->ZoneAirSolutionAlgo = DataHeatBalance::SolutionAlgo::ThirdOrder;
     951            0 :                         AlphaName(1) = "ThirdOrderBackwardDifference";
     952            0 :                         ShowWarningError(state,
     953            0 :                                          format("{}: Invalid input of {}. The default choice is assigned = {}",
     954            0 :                                                 state.dataHeatBalMgr->CurrentModuleObject,
     955            0 :                                                 state.dataIPShortCut->cAlphaFieldNames(1),
     956              :                                                 AlphaName(1)));
     957            0 :                         ShowContinueError(state, "Valid choices are: ThirdOrderBackwardDifference, AnalyticalSolution, or EulerMethod.");
     958              :                     }
     959              :                 }
     960              :             }
     961           78 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
     962            2 :                 state.dataHeatBal->doSpaceHeatBalanceSizing = static_cast<bool>(getYesNoValue(AlphaName(2)));
     963              :             }
     964           78 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     965            2 :                 state.dataHeatBal->doSpaceHeatBalanceSimulation = static_cast<bool>(getYesNoValue(AlphaName(3)));
     966              :             }
     967              :         } else {
     968          723 :             state.dataHeatBal->ZoneAirSolutionAlgo = DataHeatBalance::SolutionAlgo::ThirdOrder;
     969          723 :             AlphaName(1) = "ThirdOrderBackwardDifference";
     970              :         }
     971          801 :         if (state.dataHeatBal->OverrideZoneAirSolutionAlgo) {
     972            1 :             state.dataHeatBal->ZoneAirSolutionAlgo = DataHeatBalance::SolutionAlgo::EulerMethod;
     973            1 :             AlphaName(1) = "EulerMethod";
     974              :         }
     975              : 
     976              :         // Write Solution Algorithm to the initialization output file for User Verification
     977          801 :         constexpr const char *Format_726("! <Zone Air Solution Algorithm>, Algorithm {{ThirdOrderBackwardDifference | AnalyticalSolution | "
     978              :                                          "EulerMethod}}, Space Heat Balance Sizing, Space Heat Balance Simulation\n");
     979          801 :         print(state.files.eio, Format_726);
     980          801 :         constexpr const char *Format_727(" Zone Air Solution Algorithm, {}, {}, {}\n");
     981          801 :         print(state.files.eio,
     982              :               Format_727,
     983              :               AlphaName(1),
     984          801 :               state.dataHeatBal->doSpaceHeatBalanceSizing ? "Yes" : "No",
     985          801 :               state.dataHeatBal->doSpaceHeatBalanceSimulation ? "Yes" : "No");
     986              : 
     987              :         // A new object is added by L. Gu, 06/10
     988          801 :         state.dataHeatBalMgr->CurrentModuleObject = "ZoneAirContaminantBalance";
     989          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
     990          801 :         if (NumObjects > 0) {
     991           48 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     992           16 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
     993              :                                                                      1,
     994              :                                                                      AlphaName,
     995              :                                                                      NumAlpha,
     996              :                                                                      BuildingNumbers,
     997              :                                                                      NumNumber,
     998              :                                                                      IOStat,
     999           16 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1000           16 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1001           16 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1002           16 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1003              : 
    1004           16 :             ErrorObjectHeader eoh{routineName, state.dataHeatBalMgr->CurrentModuleObject, state.dataHeatBalMgr->CurrentModuleObject};
    1005              : 
    1006           16 :             if (NumAlpha > 0) {
    1007              :                 { // Why an extra nested scope here?
    1008           16 :                     std::string const &SELECT_CASE_var = AlphaName(1);
    1009           16 :                     if (SELECT_CASE_var == "YES") {
    1010           15 :                         state.dataContaminantBalance->Contaminant.CO2Simulation = true;
    1011           15 :                         state.dataContaminantBalance->Contaminant.SimulateContaminants = true;
    1012            1 :                     } else if (SELECT_CASE_var == "NO") {
    1013            1 :                         state.dataContaminantBalance->Contaminant.CO2Simulation = false;
    1014              :                     } else {
    1015            0 :                         state.dataContaminantBalance->Contaminant.CO2Simulation = false;
    1016            0 :                         AlphaName(1) = "NO";
    1017            0 :                         ShowWarningError(state,
    1018            0 :                                          format("{}: Invalid input of {}. The default choice is assigned = NO",
    1019            0 :                                                 state.dataHeatBalMgr->CurrentModuleObject,
    1020            0 :                                                 state.dataIPShortCut->cAlphaFieldNames(1)));
    1021              :                     }
    1022              :                 }
    1023              :             }
    1024              : 
    1025           16 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1026           15 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    1027            0 :                     ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2));
    1028            0 :                     ErrorsFound = true;
    1029           15 :                 } else if ((state.dataContaminantBalance->Contaminant.CO2OutdoorSched = Sched::GetSchedule(state, AlphaName(2))) == nullptr) {
    1030            0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2), AlphaName(2));
    1031            0 :                     ErrorsFound = true;
    1032              :                 }
    1033              :             }
    1034              : 
    1035           16 :             if (NumAlpha > 2) {
    1036              :                 {
    1037            5 :                     std::string const &SELECT_CASE_var = AlphaName(3);
    1038            5 :                     if (SELECT_CASE_var == "YES") {
    1039            3 :                         state.dataContaminantBalance->Contaminant.GenericContamSimulation = true;
    1040            3 :                         if (!state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1041            1 :                             state.dataContaminantBalance->Contaminant.SimulateContaminants = true;
    1042              :                         }
    1043            2 :                     } else if (SELECT_CASE_var == "NO") {
    1044            2 :                         state.dataContaminantBalance->Contaminant.GenericContamSimulation = false;
    1045              :                     } else {
    1046            0 :                         state.dataContaminantBalance->Contaminant.GenericContamSimulation = false;
    1047            0 :                         AlphaName(3) = "NO";
    1048            0 :                         ShowWarningError(state,
    1049            0 :                                          format("{}: Invalid input of {}. The default choice is assigned = NO",
    1050            0 :                                                 state.dataHeatBalMgr->CurrentModuleObject,
    1051            0 :                                                 state.dataIPShortCut->cAlphaFieldNames(3)));
    1052              :                     }
    1053              :                 }
    1054              : 
    1055            5 :                 if (NumAlpha == 3 && state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1056            0 :                     ShowSevereError(state,
    1057            0 :                                     format("{}, {} is required and not given.",
    1058            0 :                                            state.dataHeatBalMgr->CurrentModuleObject,
    1059            0 :                                            state.dataIPShortCut->cAlphaFieldNames(4)));
    1060            0 :                     ErrorsFound = true;
    1061            5 :                 } else if (NumAlpha > 3 && state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1062            3 :                     if ((state.dataContaminantBalance->Contaminant.genericOutdoorSched = Sched::GetSchedule(state, AlphaName(4))) == nullptr) {
    1063            0 :                         ShowSevereError(state,
    1064            0 :                                         format("{}, {} not found: {}",
    1065            0 :                                                state.dataHeatBalMgr->CurrentModuleObject,
    1066            0 :                                                state.dataIPShortCut->cAlphaFieldNames(4),
    1067              :                                                AlphaName(4)));
    1068            0 :                         ErrorsFound = true;
    1069              :                     }
    1070              :                 }
    1071              :             }
    1072              :         } else {
    1073          785 :             state.dataContaminantBalance->Contaminant.SimulateContaminants = false;
    1074          785 :             state.dataContaminantBalance->Contaminant.CO2Simulation = false;
    1075          785 :             state.dataContaminantBalance->Contaminant.GenericContamSimulation = false;
    1076          785 :             AlphaName(1) = "NO";
    1077          785 :             AlphaName(3) = "NO";
    1078              :         }
    1079              : 
    1080          801 :         Window::initWindowModel(state);
    1081              : 
    1082          801 :         constexpr const char *Format_728("! <Zone Air Carbon Dioxide Balance Simulation>, Simulation {{Yes/No}}, Carbon Dioxide Concentration\n");
    1083          801 :         print(state.files.eio, Format_728);
    1084          801 :         constexpr const char *Format_730(" Zone Air Carbon Dioxide Balance Simulation, {},{}\n");
    1085          801 :         if (state.dataContaminantBalance->Contaminant.SimulateContaminants && state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1086           15 :             print(state.files.eio, Format_730, "Yes", AlphaName(1));
    1087              :         } else {
    1088          786 :             print(state.files.eio, Format_730, "No", "N/A");
    1089              :         }
    1090              : 
    1091          801 :         constexpr const char *Format_729(
    1092              :             "! <Zone Air Generic Contaminant Balance Simulation>, Simulation {{Yes/No}}, Generic Contaminant Concentration\n");
    1093          801 :         constexpr const char *Format_731(" Zone Air Generic Contaminant Balance Simulation, {},{}\n");
    1094          801 :         print(state.files.eio, Format_729);
    1095          801 :         if (state.dataContaminantBalance->Contaminant.SimulateContaminants && state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1096            3 :             print(state.files.eio, Format_731, "Yes", AlphaName(3));
    1097              :         } else {
    1098          798 :             print(state.files.eio, Format_731, "No", "N/A");
    1099              :         }
    1100              : 
    1101              :         // A new object is added by B. Nigusse, 02/14
    1102          801 :         state.dataHeatBalMgr->CurrentModuleObject = "ZoneAirMassFlowConservation";
    1103          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
    1104          801 :         state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = false;
    1105              : 
    1106          801 :         if (NumObjects > 0) {
    1107            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1108            2 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    1109              :                                                                      1,
    1110              :                                                                      AlphaName,
    1111              :                                                                      NumAlpha,
    1112              :                                                                      BuildingNumbers,
    1113              :                                                                      NumNumber,
    1114              :                                                                      IOStat,
    1115            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1116            2 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1117            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1118            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1119            2 :             if (NumAlpha > 0) {
    1120              :                 {
    1121            2 :                     int FlowTypeNum = getEnumValue(DataHeatBalance::AdjustmentTypeNamesUC, Util::makeUPPER(AlphaName(1)));
    1122            2 :                     state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment = static_cast<DataHeatBalance::AdjustmentType>(FlowTypeNum);
    1123            2 :                     AlphaName(1) = DataHeatBalance::AdjustmentTypeNamesCC[FlowTypeNum];
    1124            2 :                     DataHeatBalance::AdjustmentType ZoneFlowAdjustment = state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment;
    1125            2 :                     if ((ZoneFlowAdjustment == DataHeatBalance::AdjustmentType::AdjustMixingOnly) ||
    1126            0 :                         (ZoneFlowAdjustment == DataHeatBalance::AdjustmentType::AdjustReturnOnly) ||
    1127            0 :                         (ZoneFlowAdjustment == DataHeatBalance::AdjustmentType::AdjustMixingThenReturn) ||
    1128              :                         (ZoneFlowAdjustment == DataHeatBalance::AdjustmentType::AdjustReturnThenMixing)) {
    1129            2 :                         state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = true;
    1130              :                     }
    1131            2 :                     if (state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment == DataHeatBalance::AdjustmentType::Invalid) {
    1132            0 :                         state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment = DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing;
    1133            0 :                         AlphaName(1) = "None";
    1134            0 :                         ShowWarningError(state,
    1135            0 :                                          format("{}: Invalid input of {}. The default choice is assigned = None",
    1136            0 :                                                 state.dataHeatBalMgr->CurrentModuleObject,
    1137            0 :                                                 state.dataIPShortCut->cAlphaFieldNames(1)));
    1138              :                     }
    1139              :                 }
    1140            2 :                 if (state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) {
    1141            2 :                     state.dataHeatBal->ZoneAirMassFlow.AdjustZoneMixingFlow = true;
    1142              :                 }
    1143              :             }
    1144            2 :             if (NumAlpha > 1) {
    1145              :                 {
    1146            2 :                     int FlowTypeNum = getEnumValue(DataHeatBalance::InfiltrationFlowTypeNamesUC, Util::makeUPPER(AlphaName(2)));
    1147            2 :                     state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment = static_cast<DataHeatBalance::InfiltrationFlow>(FlowTypeNum);
    1148            2 :                     AlphaName(2) = DataHeatBalance::InfiltrationFlowTypeNamesCC[FlowTypeNum];
    1149            3 :                     if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment == DataHeatBalance::InfiltrationFlow::Add ||
    1150            1 :                         state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment == DataHeatBalance::InfiltrationFlow::Adjust) {
    1151            2 :                         state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = true;
    1152            0 :                     } else if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment == DataHeatBalance::InfiltrationFlow::Invalid) {
    1153            0 :                         state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment = DataHeatBalance::InfiltrationFlow::Add;
    1154            0 :                         state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = true;
    1155            0 :                         AlphaName(2) = "AddInfiltrationFlow";
    1156            0 :                         ShowWarningError(state,
    1157            0 :                                          format("{}: Invalid input of {}. The default choice is assigned = AddInfiltrationFlow",
    1158            0 :                                                 state.dataHeatBalMgr->CurrentModuleObject,
    1159            0 :                                                 state.dataIPShortCut->cAlphaFieldNames(2)));
    1160              :                     }
    1161              :                 }
    1162              :             } else {
    1163            0 :                 state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment = DataHeatBalance::InfiltrationFlow::Add;
    1164            0 :                 state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = true;
    1165            0 :                 AlphaName(2) = "AddInfiltrationFlow";
    1166              :             }
    1167            2 :             if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment == DataHeatBalance::InfiltrationFlow::No) {
    1168            0 :                 AlphaName(3) = "N/A";
    1169              :             } else {
    1170            2 :                 if (NumAlpha > 2) {
    1171              :                     {
    1172            2 :                         int FlowTypeNum = getEnumValue(DataHeatBalance::InfiltrationZoneTypeNamesUC, Util::makeUPPER(AlphaName(3)));
    1173            2 :                         state.dataHeatBal->ZoneAirMassFlow.InfiltrationForZones = static_cast<DataHeatBalance::InfiltrationZoneType>(FlowTypeNum);
    1174            2 :                         AlphaName(3) = DataHeatBalance::InfiltrationZoneTypeNamesCC[FlowTypeNum];
    1175            2 :                         if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationForZones == DataHeatBalance::InfiltrationZoneType::Invalid) {
    1176            0 :                             state.dataHeatBal->ZoneAirMassFlow.InfiltrationForZones = DataHeatBalance::InfiltrationZoneType::MixingSourceZonesOnly;
    1177            0 :                             AlphaName(3) = "MixingSourceZonesOnly";
    1178            0 :                             ShowWarningError(state,
    1179            0 :                                              format("{}: Invalid input of {}. The default choice is assigned = MixingSourceZonesOnly",
    1180            0 :                                                     state.dataHeatBalMgr->CurrentModuleObject,
    1181            0 :                                                     state.dataIPShortCut->cAlphaFieldNames(3)));
    1182              :                         }
    1183              :                     }
    1184              :                 } else {
    1185            0 :                     state.dataHeatBal->ZoneAirMassFlow.InfiltrationForZones = DataHeatBalance::InfiltrationZoneType::MixingSourceZonesOnly;
    1186            0 :                     AlphaName(3) = "MixingSourceZonesOnly";
    1187              :                 }
    1188              :             }
    1189              :         } else {
    1190          799 :             state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = false;
    1191              :         }
    1192          801 :         if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment != DataHeatBalance::InfiltrationFlow::No) {
    1193            2 :             state.dataHeatBal->ZoneAirMassFlow.AdjustZoneInfiltrationFlow = true;
    1194              :         }
    1195              : 
    1196          801 :         constexpr const char *Format_732(
    1197              :             "! <Zone Air Mass Flow Balance Simulation>, Enforce Mass Balance, Adjust Zone Mixing and Return {{AdjustMixingOnly | AdjustReturnOnly | "
    1198              :             "AdjustMixingThenReturn | AdjustReturnThenMixing | None}}, Adjust Zone Infiltration "
    1199              :             "{{AddInfiltration | AdjustInfiltration | None}}, Infiltration Zones {{MixingSourceZonesOnly | AllZones}}\n");
    1200          801 :         constexpr const char *Format_733(" Zone Air Mass Flow Balance Simulation, {},{},{},{}\n");
    1201              : 
    1202          801 :         print(state.files.eio, Format_732);
    1203          801 :         if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
    1204            2 :             print(state.files.eio, Format_733, "Yes", AlphaName(1), AlphaName(2), AlphaName(3));
    1205              :         } else {
    1206          799 :             print(state.files.eio, Format_733, "No", "N/A", "N/A", "N/A");
    1207              :         }
    1208              : 
    1209              :         // A new object is added by L. Gu, 4/17
    1210          801 :         state.dataHeatBalMgr->CurrentModuleObject = "HVACSystemRootFindingAlgorithm";
    1211          801 :         NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
    1212          801 :         if (NumObjects > 0) {
    1213            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1214            1 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    1215              :                                                                      1,
    1216              :                                                                      AlphaName,
    1217              :                                                                      NumAlpha,
    1218              :                                                                      BuildingNumbers,
    1219              :                                                                      NumNumber,
    1220              :                                                                      IOStat,
    1221            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1222            1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1223            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1224            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1225            1 :             ErrorObjectHeader eoh{routineName, state.dataHeatBalMgr->CurrentModuleObject, AlphaName(1)};
    1226            1 :             if (NumAlpha > 0) {
    1227            1 :                 HVACSystemRootFinding.Algorithm = AlphaName(1);
    1228            1 :                 HVACSystemRootFinding.HVACSystemRootSolverMethod =
    1229            1 :                     static_cast<HVACSystemRootSolverAlgorithm>(getEnumValue(HVACSystemRootSolverAlgorithmUC, Util::makeUPPER(AlphaName(1))));
    1230            1 :                 if (HVACSystemRootFinding.HVACSystemRootSolverMethod == HVACSystemRootSolverAlgorithm::Invalid) {
    1231            0 :                     HVACSystemRootFinding.HVACSystemRootSolverMethod = HVACSystemRootSolverAlgorithm::RegulaFalsi;
    1232            0 :                     ShowWarningInvalidKey(
    1233            0 :                         state, eoh, state.dataIPShortCut->cAlphaFieldNames(1), AlphaName(1), "Invalid input. The default choice is assigned.");
    1234            0 :                     ShowContinueError(
    1235              :                         state, "Valid choices are: RegulaFalsi, Bisection, BisectionThenRegulaFalsi, RegulaFalsiThenBisection, or Alternation.");
    1236              :                 }
    1237              :             }
    1238            1 :             if (NumNumber > 0) {
    1239            1 :                 HVACSystemRootFinding.NumOfIter = BuildingNumbers(1);
    1240              :             }
    1241              :         } else {
    1242          800 :             HVACSystemRootFinding.Algorithm = "RegulaFalsi";
    1243          800 :             HVACSystemRootFinding.HVACSystemRootSolverMethod = HVACSystemRootSolverAlgorithm::RegulaFalsi;
    1244              :         }
    1245              : 
    1246              :         // Write Solution Algorithm to the initialization output file for User Verification
    1247          801 :         constexpr const char *Format_734(
    1248              :             "! <HVACSystemRootFindingAlgorithm>, Value {{RegulaFalsi | Bisection | BisectionThenRegulaFalsi | RegulaFalsiThenBisection}}\n");
    1249          801 :         constexpr const char *Format_735(" HVACSystemRootFindingAlgorithm, {}\n");
    1250          801 :         print(state.files.eio, Format_734);
    1251          801 :         print(state.files.eio, Format_735, HVACSystemRootFinding.Algorithm);
    1252          801 :     }
    1253              : 
    1254          801 :     void GetSiteAtmosphereData(EnergyPlusData &state, bool &ErrorsFound)
    1255              :     {
    1256              : 
    1257              :         // SUBROUTINE INFORMATION:
    1258              :         //       AUTHOR         Peter Graham Ellis
    1259              :         //       DATE WRITTEN   January 2006
    1260              : 
    1261              :         // PURPOSE OF THIS SUBROUTINE:
    1262              :         // Reads the input data for the SITE ATMOSPHERIC VARIATION object.
    1263              : 
    1264              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1265          801 :         Array1D_string AlphArray(1); // Character string data
    1266          801 :         Array1D<Real64> NumArray(3); // Numeric data
    1267              : 
    1268              :         // Formats
    1269          801 :         constexpr const char *Format_720("Environment:Site Atmospheric Variation,{:.3R},{:.3R},{:.6R}\n");
    1270              : 
    1271          801 :         state.dataHeatBalMgr->CurrentModuleObject = "Site:HeightVariation";
    1272          801 :         int NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
    1273              : 
    1274          801 :         if (NumObjects == 1) {
    1275              :             int NumAlphas; // Number of elements in the alpha array
    1276              :             int NumNums;   // Number of elements in the numeric array
    1277              :             int IOStat;    // IO Status when calling get input subroutine
    1278            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1279            1 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    1280              :                                                                      1,
    1281              :                                                                      AlphArray,
    1282              :                                                                      NumAlphas,
    1283              :                                                                      NumArray,
    1284              :                                                                      NumNums,
    1285              :                                                                      IOStat,
    1286            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1287            1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1288            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1289            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1290              : 
    1291            1 :             if (NumNums > 0) {
    1292            1 :                 state.dataEnvrn->SiteWindExp = NumArray(1);
    1293              :             }
    1294            1 :             if (NumNums > 1) {
    1295            1 :                 state.dataEnvrn->SiteWindBLHeight = NumArray(2);
    1296              :             }
    1297            1 :             if (NumNums > 2) {
    1298            1 :                 state.dataEnvrn->SiteTempGradient = NumArray(3);
    1299              :             }
    1300              : 
    1301          800 :         } else if (NumObjects > 1) {
    1302            0 :             ShowSevereError(state, format("Too many {} objects, only 1 allowed.", state.dataHeatBalMgr->CurrentModuleObject));
    1303            0 :             ErrorsFound = true;
    1304              :         } else { //  None entered
    1305              :             // IDD defaults would have this:
    1306              :             // Building object defaults use Terrain to set SiteWindExp and SiteWindBLHeight but would
    1307              :             // be overridden by a Site Atmospheric Variation Object.
    1308              :             // SiteWindExp = 0.22
    1309              :             // SiteWindBLHeight = 370.0
    1310          800 :             state.dataEnvrn->SiteTempGradient = 0.0065;
    1311              :         }
    1312              : 
    1313              :         // Write to the initialization output file
    1314          801 :         print(state.files.eio,
    1315              :               "! <Environment:Site Atmospheric Variation>,Wind Speed Profile Exponent {{}},Wind Speed Profile Boundary "
    1316              :               "Layer Thickness {{m}},Air Temperature Gradient Coefficient {{K/m}}\n");
    1317              : 
    1318          801 :         print(state.files.eio, Format_720, state.dataEnvrn->SiteWindExp, state.dataEnvrn->SiteWindBLHeight, state.dataEnvrn->SiteTempGradient);
    1319          801 :     }
    1320              : 
    1321          801 :     void GetConstructData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    1322              :     {
    1323              : 
    1324              :         // SUBROUTINE INFORMATION:
    1325              :         //       AUTHOR         Richard Liesen
    1326              :         //       DATE WRITTEN   September 1997
    1327              :         //       MODIFIED       January 2003, FCW: accommodate between-glass shading device
    1328              :         //                      July 2009, TH: added constructions defined with F and C factors
    1329              : 
    1330              :         // PURPOSE OF THIS SUBROUTINE:
    1331              :         // This file reads the input through the input processor for Constructions.
    1332              :         // Data read in this routine is stored in a derived type (Construct)
    1333              :         // defined in the DataHeatBalance module.
    1334              :         // This subroutine only sets those parameters which must be obtained
    1335              :         // from the input file--all other portions of the Construct derived
    1336              :         // type are set during the initializations.
    1337              : 
    1338              :         // Using/Aliasing
    1339              :         using namespace DataStringGlobals;
    1340              : 
    1341              :         static constexpr std::string_view routineName = "GetConstructData";
    1342              : 
    1343              :         // If UniqueConstructionNames size, then input has already been gotten
    1344          801 :         if (state.dataHeatBalMgr->UniqueConstructNames.size()) {
    1345            0 :             return;
    1346              :         }
    1347              : 
    1348              :         int ConstructNumAlpha;                                                   // Number of construction alpha names being passed
    1349              :         int DummyNumProp;                                                        // dummy variable for properties being passed
    1350              :         int IOStat;                                                              // IO Status when calling get input subroutine
    1351          801 :         Array1D_string ConstructAlphas({0, Construction::MaxLayersInConstruct}); // Construction Alpha names defined
    1352          801 :         Array1D<Real64> DummyProps(5);                                           // Temporary array to transfer construction properties
    1353              :         int TotRegConstructs; // Number of "regular" constructions (no embedded sources or sinks and
    1354              : 
    1355              :         int TotFfactorConstructs; // Number of slabs-on-grade or underground floor constructions defined with F factors
    1356              :         int TotCfactorConstructs; // Number of underground wall constructions defined with C factors
    1357              : 
    1358              :         // int TotSourceConstructs;  // Number of constructions with embedded sources or sinks
    1359              :         int TotWindow5Constructs; // Number of constructions from Window5 data file
    1360              :         bool ConstructionFound;   // True if input window construction name is found in the
    1361              :         //  Window5 data file
    1362              :         bool EOFonW5File; // True if EOF encountered reading Window5 data file
    1363              : 
    1364          801 :         Array1D_string WConstructNames;
    1365              : 
    1366          801 :         auto &s_ipsc = state.dataIPShortCut;
    1367          801 :         auto &s_mat = state.dataMaterial;
    1368              : 
    1369              :         // Get the Total number of Constructions from the input
    1370          801 :         TotRegConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction");
    1371          801 :         int totAirBoundaryConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:AirBoundary");
    1372              : 
    1373          801 :         TotFfactorConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:FfactorGroundFloor");
    1374          801 :         TotCfactorConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:CfactorUndergroundWall");
    1375              : 
    1376          801 :         if (TotFfactorConstructs > 0) {
    1377           15 :             state.dataHeatBal->NoFfactorConstructionsUsed = false;
    1378              :         }
    1379              : 
    1380          801 :         if (TotCfactorConstructs > 0) {
    1381            7 :             state.dataHeatBal->NoCfactorConstructionsUsed = false;
    1382              :         }
    1383              : 
    1384         1602 :         state.dataBSDFWindow->TotComplexFenStates =
    1385          801 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:ComplexFenestrationState");
    1386          801 :         TotWindow5Constructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:WindowDataFile");
    1387         1602 :         state.dataWindowEquivLayer->TotWinEquivLayerConstructs =
    1388          801 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:WindowEquivalentLayer");
    1389              : 
    1390          801 :         WConstructNames.allocate(TotWindow5Constructs);
    1391              : 
    1392         3204 :         state.dataHeatBal->TotConstructs = TotRegConstructs + TotFfactorConstructs + TotCfactorConstructs + totAirBoundaryConstructs +
    1393          801 :                                            state.dataBSDFWindow->TotComplexFenStates + state.dataWindowEquivLayer->TotWinEquivLayerConstructs;
    1394              : 
    1395          801 :         state.dataHeatBal->NominalRforNominalUCalculation.dimension(state.dataHeatBal->TotConstructs, 0.0);
    1396          801 :         state.dataHeatBal->NominalU.dimension(state.dataHeatBal->TotConstructs, 0.0);
    1397          801 :         state.dataHeatBal->NominalUBeforeAdjusted.dimension(state.dataHeatBal->TotConstructs, 0.0);
    1398          801 :         state.dataHeatBal->CoeffAdjRatio.dimension(state.dataHeatBal->TotConstructs, 1.0);
    1399              : 
    1400              :         // Allocate the array to the number of constructions/initialize selected variables
    1401          801 :         state.dataConstruction->Construct.allocate(state.dataHeatBal->TotConstructs);
    1402          801 :         state.dataHeatBalMgr->UniqueConstructNames.reserve(state.dataHeatBal->TotConstructs);
    1403              :         // Note: If TotWindow5Constructs > 0, additional constructions are created in
    1404              :         // subr. SearchWindow5DataFile corresponding to those found on the data file.
    1405         6858 :         for (auto &e : state.dataConstruction->Construct) {
    1406              :             // Initialize CTF and History terms
    1407         6057 :             e.NumCTFTerms = 0;
    1408         6057 :             e.NumHistories = 0;
    1409              : 
    1410              :             // Initialize some heat source/sink variables
    1411         6057 :             e.SourceSinkPresent = false; // "default" is no source or sink present
    1412         6057 :             e.SolutionDimensions = 1;    // "default" is 1-D heat transfer
    1413         6057 :             e.SourceAfterLayer = 0;      // this has no meaning if a source/sink is not present
    1414         6057 :             e.TempAfterLayer = 0;        // this has no meaning if a source/sink is not present
    1415         6057 :             e.ThicknessPerpend = 0.0;    // this has no meaning if a source/sink is not present
    1416              : 
    1417         6057 :             e.W5FrameDivider = 0;
    1418         6057 :             e.FromWindow5DataFile = false;
    1419              : 
    1420              :             // these Construct arrays dimensioned based on MaxSolidWinLayers
    1421         6057 :             e.setArraysBasedOnMaxSolidWinLayers(state);
    1422              :         }
    1423              : 
    1424          801 :         int ConstrNum = 0;
    1425              : 
    1426          801 :         s_ipsc->cCurrentModuleObject = "Construction";
    1427         6619 :         for (int Loop = 1; Loop <= TotRegConstructs; ++Loop) { // Loop through all constructs in the input...
    1428              : 
    1429              :             // Get the object names for each construction from the input processor
    1430        17454 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1431         5818 :                                                                      s_ipsc->cCurrentModuleObject,
    1432              :                                                                      Loop,
    1433              :                                                                      ConstructAlphas,
    1434              :                                                                      ConstructNumAlpha,
    1435              :                                                                      DummyProps,
    1436              :                                                                      DummyNumProp,
    1437              :                                                                      IOStat,
    1438         5818 :                                                                      s_ipsc->lNumericFieldBlanks,
    1439         5818 :                                                                      s_ipsc->lAlphaFieldBlanks,
    1440         5818 :                                                                      s_ipsc->cAlphaFieldNames,
    1441         5818 :                                                                      s_ipsc->cNumericFieldNames);
    1442              : 
    1443         5818 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, ConstructAlphas(1)};
    1444              : 
    1445        11636 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    1446         5818 :                                                          state.dataHeatBalMgr->UniqueConstructNames,
    1447         5818 :                                                          ConstructAlphas(0),
    1448         5818 :                                                          state.dataHeatBalMgr->CurrentModuleObject,
    1449         5818 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    1450              :                                                          ErrorsFound)) {
    1451            0 :                 continue;
    1452              :             }
    1453              : 
    1454         5818 :             ++ConstrNum;
    1455         5818 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    1456              :             // Assign Construction name to the Derived Type using the zeroth position of the array
    1457         5818 :             thisConstruct.Name = ConstructAlphas(0);
    1458              : 
    1459              :             // Set the total number of layers for the construction
    1460         5818 :             thisConstruct.TotLayers = ConstructNumAlpha - 1;
    1461              : 
    1462              :             // Loop through all of the layers of the construct to match the material names.
    1463              :             // The loop index is the number minus 1
    1464              : 
    1465        19489 :             for (int GlassLayer = 0, Layer = 1; Layer <= ConstructNumAlpha - 1; ++Layer) {
    1466              : 
    1467              :                 // Find the material in the list of materials
    1468        13671 :                 thisConstruct.LayerPoint(Layer) = Material::GetMaterialNum(state, ConstructAlphas(Layer));
    1469              : 
    1470        13671 :                 if (thisConstruct.LayerPoint(Layer) == 0) {
    1471            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(Layer), ConstructAlphas(Layer));
    1472            0 :                     ErrorsFound = true;
    1473            0 :                     continue;
    1474              :                 }
    1475              : 
    1476        13671 :                 auto const *mat = s_mat->materials(thisConstruct.LayerPoint(Layer));
    1477        13671 :                 if (mat->group == Material::Group::Glass) {
    1478         1809 :                     ++GlassLayer;
    1479        11862 :                 } else if (mat->group == Material::Group::GlassEQL || mat->group == Material::Group::ShadeEQL ||
    1480        11862 :                            mat->group == Material::Group::DrapeEQL || mat->group == Material::Group::BlindEQL ||
    1481        11862 :                            mat->group == Material::Group::ScreenEQL || mat->group == Material::Group::WindowGapEQL) {
    1482            0 :                     ShowSevereError(state, format("Invalid material layer type in window {} = {}", s_ipsc->cCurrentModuleObject, thisConstruct.Name));
    1483            0 :                     ShowContinueError(
    1484              :                         state,
    1485            0 :                         format("Equivalent Layer material type = {} is allowed only in Construction:WindowEquivalentLayer window object.",
    1486              :                                ConstructAlphas(Layer)));
    1487            0 :                     ErrorsFound = true;
    1488            0 :                     continue;
    1489        11862 :                 } else if (mat->group == Material::Group::GlassTCParent) {
    1490            1 :                     ++GlassLayer;
    1491              :                     // reset layer pointer to the first glazing in the TC GlazingGroup
    1492            1 :                     auto const *matGlassTC = dynamic_cast<Material::MaterialGlassTC const *>(mat);
    1493            1 :                     assert(matGlassTC != nullptr);
    1494              : 
    1495            1 :                     thisConstruct.LayerPoint(Layer) = matGlassTC->matRefs(1).matNum;
    1496            1 :                     thisConstruct.isTCWindow = true;
    1497            1 :                     thisConstruct.isTCMaster = true;
    1498            1 :                     thisConstruct.TCMasterConstrNum = ConstrNum;
    1499            1 :                     thisConstruct.TCMasterMatNum = matGlassTC->Num;
    1500            1 :                     thisConstruct.TCGlassNum = GlassLayer; // the TC glass layer ID
    1501            1 :                     thisConstruct.TCLayerNum = Layer;
    1502            1 :                     thisConstruct.TypeIsWindow = true;
    1503              :                 }
    1504              : 
    1505        13671 :                 state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) += mat->NominalR;
    1506        13671 :                 if (mat->group == Material::Group::Regular && !mat->ROnly) {
    1507         9354 :                     state.dataHeatBal->NoRegularMaterialsUsed = false;
    1508              :                 }
    1509              : 
    1510              :             } // ...end of the Layer DO loop
    1511              : 
    1512              :         } // ...end of Regular Construction DO loop
    1513              : 
    1514          801 :         TotRegConstructs = ConstrNum;
    1515              : 
    1516              :         // Added TH 7/2009 for underground walls and floors constructions
    1517          801 :         if (TotFfactorConstructs + TotCfactorConstructs >= 1) {
    1518           21 :             CreateFCfactorConstructions(state, ConstrNum, ErrorsFound);
    1519           21 :             if (ErrorsFound) {
    1520            0 :                 ShowSevereError(state, "Errors found in creating the constructions defined with Ffactor or Cfactor method");
    1521              :             }
    1522           21 :             TotRegConstructs += TotFfactorConstructs + TotCfactorConstructs;
    1523              :         }
    1524              : 
    1525          801 :         if (totAirBoundaryConstructs >= 1) {
    1526            5 :             CreateAirBoundaryConstructions(state, ConstrNum, ErrorsFound);
    1527            5 :             if (ErrorsFound) {
    1528            0 :                 ShowSevereError(state, "Errors found in creating the constructions defined with Construction:AirBoundary.");
    1529              :             }
    1530            5 :             TotRegConstructs += totAirBoundaryConstructs;
    1531              :         }
    1532              : 
    1533              :         // Added BG 6/2010 for complex fenestration
    1534          801 :         if (state.dataBSDFWindow->TotComplexFenStates > 0) {
    1535           10 :             SetupComplexFenestrationStateInput(state, ConstrNum, ErrorsFound);
    1536           10 :             if (ErrorsFound) {
    1537            0 :                 ShowSevereError(state, "Errors found in processing complex fenestration input");
    1538              :             }
    1539           10 :             TotRegConstructs += state.dataBSDFWindow->TotComplexFenStates;
    1540              :         }
    1541              : 
    1542          801 :         state.dataHeatBalMgr->CurrentModuleObject = "ConstructionProperty:InternalHeatSource";
    1543              : 
    1544          801 :         auto instances = state.dataInputProcessing->inputProcessor->epJSON.find(state.dataHeatBalMgr->CurrentModuleObject);
    1545          801 :         if (instances != state.dataInputProcessing->inputProcessor->epJSON.end()) {
    1546           36 :             state.dataHeatBal->AnyInternalHeatSourceInInput = true;
    1547           36 :             auto &instancesValue = instances.value();
    1548           80 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    1549           44 :                 auto const &fields = instance.value();
    1550           44 :                 std::string const thisObjectName = Util::makeUPPER(instance.key());
    1551              : 
    1552           88 :                 std::string construction_name = Util::makeUPPER(fields.at("construction_name").get<std::string>());
    1553           88 :                 int source_after_layer_number = fields.at("thermal_source_present_after_layer_number").get<int>();
    1554           88 :                 int calculation_after_layer_number = fields.at("temperature_calculation_requested_after_layer_number").get<int>();
    1555           44 :                 int ctf_dimensions = fields.at("dimensions_for_the_ctf_calculation").get<int>();
    1556           44 :                 if ((ctf_dimensions < 1) || (ctf_dimensions > 2)) {
    1557            0 :                     ShowWarningError(state, "ConstructionProperty:InternalHeatSource must be either 1- or 2-D.  Reset to 1-D solution.");
    1558            0 :                     ShowContinueError(state, format("Construction={} is affected.", construction_name));
    1559            0 :                     ctf_dimensions = 1;
    1560              :                 }
    1561           44 :                 Real64 tube_spacing = fields.at("tube_spacing").get<Real64>();
    1562           44 :                 Real64 calculation_position = 0.0;
    1563           44 :                 auto const twoDimTempCalcPos = fields.find("two_dimensional_temperature_calculation_position");
    1564           44 :                 if (twoDimTempCalcPos != fields.end()) {
    1565           44 :                     calculation_position = twoDimTempCalcPos.value().get<Real64>();
    1566              :                 }
    1567              : 
    1568              :                 // Find the construction
    1569           44 :                 int construction_index = Util::FindItemInList(construction_name, state.dataConstruction->Construct);
    1570              : 
    1571           44 :                 if (construction_index == 0) {
    1572            0 :                     ShowSevereError(state,
    1573            0 :                                     format("Did not find matching construction for {} {}, missing construction = {}",
    1574            0 :                                            state.dataHeatBalMgr->CurrentModuleObject,
    1575              :                                            thisObjectName,
    1576              :                                            construction_name));
    1577            0 :                     ErrorsFound = true;
    1578            0 :                     continue;
    1579              :                 }
    1580              : 
    1581           44 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(state.dataHeatBalMgr->CurrentModuleObject, instance.key());
    1582              : 
    1583           44 :                 auto &thisConstruct = state.dataConstruction->Construct(construction_index);
    1584              : 
    1585              :                 // May need some additional validation of the construction here
    1586           44 :                 if (thisConstruct.SourceSinkPresent) {
    1587              :                     // Emulate old behavior by disallowing two sources in a single material
    1588            0 :                     ShowSevereError(
    1589              :                         state,
    1590            0 :                         format("Construction {} has more than one internal heat source referencing it, which is not allowed", construction_name));
    1591            0 :                     ErrorsFound = true;
    1592            0 :                     continue;
    1593              :                 }
    1594              : 
    1595           44 :                 thisConstruct.SourceSinkPresent = true;
    1596           44 :                 thisConstruct.SourceAfterLayer = source_after_layer_number;
    1597           44 :                 thisConstruct.TempAfterLayer = calculation_after_layer_number;
    1598           44 :                 thisConstruct.SolutionDimensions = ctf_dimensions;
    1599           44 :                 thisConstruct.ThicknessPerpend = thisConstruct.setThicknessPerpendicular(state, tube_spacing);
    1600           44 :                 thisConstruct.userTemperatureLocationPerpendicular =
    1601           44 :                     thisConstruct.setUserTemperatureLocationPerpendicular(state, calculation_position);
    1602              : 
    1603              :                 // Set the total number of layers for the construction
    1604           44 :                 if ((thisConstruct.SourceAfterLayer >= thisConstruct.TotLayers) || (thisConstruct.SourceAfterLayer <= 0)) {
    1605            0 :                     ShowWarningError(state, format("Construction {} must have a source that is between two layers", thisConstruct.Name));
    1606            0 :                     ShowContinueError(state, "The source after layer parameter has been set to one less than the number of layers.");
    1607            0 :                     thisConstruct.SourceAfterLayer = thisConstruct.TotLayers - 1;
    1608              :                 }
    1609           44 :                 if ((thisConstruct.TempAfterLayer >= thisConstruct.TotLayers) || (thisConstruct.TempAfterLayer <= 0)) {
    1610            0 :                     ShowWarningError(state,
    1611            0 :                                      format("Construction {} must have a temperature calculation that is between two layers", thisConstruct.Name));
    1612            0 :                     ShowContinueError(state, "The temperature calculation after layer parameter has been set to one less than the number of layers.");
    1613            0 :                     thisConstruct.TempAfterLayer = thisConstruct.TotLayers - 1;
    1614              :                 }
    1615           80 :             }
    1616              :         }
    1617              : 
    1618          801 :         state.dataHeatBal->TotConstructs = TotRegConstructs;
    1619              : 
    1620          801 :         if (state.dataHeatBal->TotConstructs > 0 && (state.dataHeatBal->NoRegularMaterialsUsed && state.dataHeatBal->NoCfactorConstructionsUsed &&
    1621            0 :                                                      state.dataHeatBal->NoFfactorConstructionsUsed)) {
    1622            0 :             ShowWarningError(state, "This building has no thermal mass which can cause an unstable solution.");
    1623            0 :             ShowContinueError(state, "Use Material object for all opaque material definitions except very light insulation layers.");
    1624              :         }
    1625              : 
    1626          801 :         ConstrNum = 0;
    1627          801 :         state.dataHeatBalMgr->CurrentModuleObject = "Construction:WindowEquivalentLayer";
    1628          804 :         for (int Loop = 1; Loop <= state.dataWindowEquivLayer->TotWinEquivLayerConstructs;
    1629              :              ++Loop) { // Loop through all constructs with Window EquivalentLayer ...
    1630              : 
    1631              :             // Get the object names for each construction from the input processor
    1632            9 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1633            3 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    1634              :                                                                      Loop,
    1635              :                                                                      ConstructAlphas,
    1636              :                                                                      ConstructNumAlpha,
    1637              :                                                                      DummyProps,
    1638              :                                                                      DummyNumProp,
    1639              :                                                                      IOStat,
    1640            3 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1641            3 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1642            3 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1643            3 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1644            6 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    1645            3 :                                                          state.dataHeatBalMgr->UniqueConstructNames,
    1646            3 :                                                          ConstructAlphas(0),
    1647            3 :                                                          state.dataHeatBalMgr->CurrentModuleObject,
    1648            3 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    1649              :                                                          ErrorsFound)) {
    1650            0 :                 continue;
    1651              :             }
    1652              : 
    1653            3 :             ++ConstrNum;
    1654            3 :             auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    1655              :             // Assign Construction name to the Derived Type using the zeroth position of the array
    1656            3 :             state.dataConstruction->Construct(TotRegConstructs + ConstrNum).Name = ConstructAlphas(0);
    1657              : 
    1658              :             // Set the total number of layers for the construction
    1659            3 :             state.dataConstruction->Construct(TotRegConstructs + ConstrNum).TotLayers = ConstructNumAlpha - 1;
    1660            3 :             if (state.dataConstruction->Construct(TotRegConstructs + ConstrNum).TotLayers < 1) {
    1661            0 :                 ShowSevereError(state,
    1662            0 :                                 format("Construction {} must have at least a single layer",
    1663            0 :                                        state.dataConstruction->Construct(TotRegConstructs + ConstrNum).Name));
    1664            0 :                 ErrorsFound = true;
    1665              :             }
    1666              : 
    1667              :             // Loop through all of the layers of the construct to match the material names.
    1668              :             // The loop index is the number minus 1
    1669           22 :             for (int Layer = 1; Layer <= ConstructNumAlpha - 1; ++Layer) {
    1670              : 
    1671              :                 // Find the material in the list of materials
    1672           19 :                 state.dataConstruction->Construct(TotRegConstructs + ConstrNum).LayerPoint(Layer) =
    1673           19 :                     Material::GetMaterialNum(state, ConstructAlphas(Layer));
    1674              : 
    1675           19 :                 if (state.dataConstruction->Construct(TotRegConstructs + ConstrNum).LayerPoint(Layer) == 0) {
    1676            0 :                     ShowSevereError(state,
    1677            0 :                                     format("Did not find matching material for {} {}, missing material = {}",
    1678            0 :                                            state.dataHeatBalMgr->CurrentModuleObject,
    1679            0 :                                            thisConstruct.Name,
    1680              :                                            ConstructAlphas(Layer)));
    1681            0 :                     ErrorsFound = true;
    1682              :                 } else {
    1683           19 :                     auto const *mat = s_mat->materials(state.dataConstruction->Construct(TotRegConstructs + ConstrNum).LayerPoint(Layer));
    1684           19 :                     if (!((mat->group == Material::Group::GlassEQL) || (mat->group == Material::Group::ShadeEQL) ||
    1685            9 :                           (mat->group == Material::Group::DrapeEQL) || (mat->group == Material::Group::BlindEQL) ||
    1686            9 :                           (mat->group == Material::Group::ScreenEQL) || (mat->group == Material::Group::WindowGapEQL))) {
    1687            0 :                         ShowSevereError(state,
    1688            0 :                                         format("Invalid material layer type in window {} = {}",
    1689            0 :                                                state.dataHeatBalMgr->CurrentModuleObject,
    1690            0 :                                                state.dataConstruction->Construct(TotRegConstructs + ConstrNum).Name));
    1691            0 :                         ShowContinueError(state,
    1692            0 :                                           format("...Window layer = {} is not allowed in Construction:WindowEquivalentLayer window object.",
    1693              :                                                  ConstructAlphas(Layer)));
    1694            0 :                         ShowContinueError(state, "Only materials of type Material:*:EquivalentLayer are allowed");
    1695            0 :                         ErrorsFound = true;
    1696              :                     }
    1697              : 
    1698           19 :                     if (ConstructNumAlpha <= 2) {
    1699              : 
    1700              :                     } else {
    1701           19 :                         auto const *mat = s_mat->materials(state.dataConstruction->Construct(TotRegConstructs + ConstrNum).LayerPoint(Layer));
    1702           19 :                         state.dataHeatBal->NominalRforNominalUCalculation(TotRegConstructs + ConstrNum) += mat->NominalR;
    1703              :                     }
    1704              :                 }
    1705              : 
    1706              :             } // Layer loop
    1707            3 :             state.dataConstruction->Construct(TotRegConstructs + ConstrNum).EQLConsPtr = ConstrNum;
    1708            3 :             state.dataConstruction->Construct(TotRegConstructs + ConstrNum).WindowTypeEQL = true;
    1709              :         } // TotWinEquivLayerConstructs loop
    1710              : 
    1711          801 :         state.dataWindowEquivLayer->TotWinEquivLayerConstructs = ConstrNum;
    1712          801 :         TotRegConstructs += state.dataWindowEquivLayer->TotWinEquivLayerConstructs;
    1713          801 :         state.dataHeatBal->TotConstructs = TotRegConstructs;
    1714              :         //-------------------------------------------------------------------------------
    1715          801 :         ConstrNum = 0;
    1716              : 
    1717          801 :         state.dataHeatBalMgr->CurrentModuleObject = "Construction:WindowDataFile";
    1718          806 :         for (int Loop = 1; Loop <= TotWindow5Constructs; ++Loop) { // Loop through all Window5 constructions. These constructions come
    1719              :                                                                    // from the Window5 data file and can be referenced only by windows
    1720              : 
    1721              :             // Get the object names for each construction from the input processor
    1722           15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1723            5 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    1724              :                                                                      Loop,
    1725              :                                                                      ConstructAlphas,
    1726              :                                                                      ConstructNumAlpha,
    1727              :                                                                      DummyProps,
    1728              :                                                                      DummyNumProp,
    1729              :                                                                      IOStat,
    1730            5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1731            5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1732            5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1733            5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1734              : 
    1735            5 :             ++ConstrNum;
    1736            5 :             WConstructNames(ConstrNum) = ConstructAlphas(0);
    1737              : 
    1738              :             // Obtain the data
    1739            5 :             if (DummyNumProp != 0) {
    1740            0 :                 ShowSevereError(state, format("Construction From Window5 Data File: there should be no numerical inputs for {}", ConstructAlphas(0)));
    1741            0 :                 ErrorsFound = true;
    1742            0 :                 continue;
    1743              :             }
    1744              : 
    1745              :             // See if this construction is in the W5DataFile produced by the WINDOW 5 program;
    1746              :             // if so, ConstructionFound will be set to true and the Material objects
    1747              :             // associated with the construction will be created in subr. SearchWindow5DataFile.
    1748              :             // (If the matching construction on the Window5 data file has two glazing systems, a
    1749              :             // second construction and its associated materials will be created in subr.
    1750              :             // SearchWindow5DataFile and TotConstructs WILL BE INCREMENTED BY 1 in that routine.
    1751              :             // A FrameAndDivider object will also be created if window on data file has a
    1752              :             // frame or divider.)
    1753              : 
    1754            5 :             fs::path window5DataFilePath;
    1755            5 :             if (ConstructAlphas(1) == "") {
    1756            0 :                 window5DataFilePath = state.dataStrGlobals->CurrentWorkingFolder / "Window5DataFile.dat";
    1757              :             } else {
    1758            5 :                 window5DataFilePath = ConstructAlphas(1);
    1759              :             }
    1760            5 :             DisplayString(state, "Searching Window5 data file for Construction=" + ConstructAlphas(0));
    1761              : 
    1762            5 :             SearchWindow5DataFile(state, window5DataFilePath, ConstructAlphas(0), ConstructionFound, EOFonW5File, ErrorsFound);
    1763              : 
    1764            5 :             if (EOFonW5File || !ConstructionFound) {
    1765            0 :                 DisplayString(state, "--Construction not found");
    1766            0 :                 ErrorsFound = true;
    1767            0 :                 ShowSevereError(state, format("No match on WINDOW5 data file for Construction={}, or error in data file.", ConstructAlphas(0)));
    1768            0 :                 ShowContinueError(state, format("...Looking on file={}", window5DataFilePath)); // TODO: call getAbsolutePath maybe?
    1769            0 :                 continue;
    1770              :             }
    1771              : 
    1772            5 :         } // ...end of Window5 Constructions DO loop
    1773              : 
    1774          801 :         WConstructNames.deallocate();
    1775              : 
    1776              :         // set some (default) properties of the Construction Derived Type
    1777         6863 :         for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
    1778              : 
    1779         6062 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    1780              :             // For air boundaries, skip TypeIsAirBoundary
    1781         6062 :             if (thisConstruct.TypeIsAirBoundary) {
    1782            5 :                 continue;
    1783              :             }
    1784         6057 :             if (state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) != 0.0) {
    1785         6057 :                 state.dataHeatBal->NominalU(ConstrNum) = 1.0 / state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum);
    1786              :             } else {
    1787            0 :                 if (!thisConstruct.WindowTypeEQL) {
    1788            0 :                     ShowSevereError(state, format("Nominal U is zero, for construction={}", thisConstruct.Name));
    1789            0 :                     ErrorsFound = true;
    1790              :                 }
    1791              :             }
    1792              : 
    1793         6057 :             DataHeatBalance::CheckAndSetConstructionProperties(state, ConstrNum, ErrorsFound);
    1794              : 
    1795              :         } // End of ConstrNum DO loop
    1796          801 :     }
    1797              : 
    1798          801 :     void GetBuildingData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    1799              :     {
    1800              : 
    1801              :         // SUBROUTINE INFORMATION:
    1802              :         //       AUTHOR         Linda K. Lawrie
    1803              :         //       DATE WRITTEN   November 1997
    1804              :         //       MODIFIED       October 1998, FW; May 1999 FW; Oct 2004 LKL
    1805              : 
    1806              :         // PURPOSE OF THIS SUBROUTINE:
    1807              :         // This routine calls other routines to get the Zone, and Surface data
    1808              :         //  from the input file.
    1809              : 
    1810              :         // METHODOLOGY EMPLOYED:
    1811              :         // The GetObjectItem routines are employed to retrieve the data.
    1812              : 
    1813          801 :         SolarShading::GetShadowingInput(state);
    1814              : 
    1815          801 :         GetZoneData(state, ErrorsFound); // Read Zone data from input file
    1816              : 
    1817          801 :         SurfaceGeometry::SetupZoneGeometry(state, ErrorsFound);
    1818          801 :     }
    1819              : 
    1820          801 :     void GetZoneData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    1821              :     {
    1822              : 
    1823              :         // SUBROUTINE INFORMATION:
    1824              :         //       AUTHOR         Linda K. Lawrie
    1825              :         //       DATE WRITTEN   November 1997
    1826              :         //       MODIFIED       PGE: Added ZONE LIST and ZONE GROUP objects, Nov 2003
    1827              :         //                      RJH: Added init of DElight member of ZoneDaylight object, Jan 2004
    1828              :         //                      JG: Added Part of Total Floor Area field March 2006
    1829              : 
    1830              :         // PURPOSE OF THIS SUBROUTINE:
    1831              :         // This subroutine gets the zone data for each zone in the input file.
    1832              : 
    1833              :         // METHODOLOGY EMPLOYED:
    1834              :         // The GetObjectItem routines are employed to retrieve the data.
    1835              : 
    1836              :         // REFERENCES:
    1837              :         // IDD Definition for Zone object
    1838              : 
    1839              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1840          801 :         constexpr const char *RoutineName("GetZoneData: ");
    1841              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1842              :         int NumAlphas;
    1843              :         int NumNumbers;
    1844              :         int IOStatus;
    1845              :         std::string::size_type TMP;
    1846              :         int ZoneNum;
    1847          801 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    1848          801 :         cCurrentModuleObject = "Zone";
    1849          801 :         state.dataGlobal->NumOfZones = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1850              : 
    1851          801 :         state.dataHeatBal->Zone.allocate(state.dataGlobal->NumOfZones);
    1852          801 :         state.dataDayltg->ZoneDaylight.allocate(state.dataGlobal->NumOfZones);
    1853              :         // always allocate as the data structure is needed in output variable Zone Heat Index, Zone Humidity Index
    1854          801 :         state.dataHeatBal->Resilience.allocate(state.dataGlobal->NumOfZones);
    1855              : 
    1856          801 :         int ZoneLoop = 0;
    1857              : 
    1858         6002 :         for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1859              : 
    1860         5201 :             state.dataIPShortCut->rNumericArgs = 0.0; // Zero out just in case
    1861        10402 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1862              :                                                                      cCurrentModuleObject,
    1863              :                                                                      Loop,
    1864         5201 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1865              :                                                                      NumAlphas,
    1866         5201 :                                                                      state.dataIPShortCut->rNumericArgs,
    1867              :                                                                      NumNumbers,
    1868              :                                                                      IOStatus,
    1869         5201 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1870         5201 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1871         5201 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1872         5201 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1873         5201 :             TMP = index(state.dataIPShortCut->cAlphaArgs(1), char(1));
    1874         5201 :             while (TMP != std::string::npos) {
    1875            0 :                 state.dataIPShortCut->cAlphaArgs(1)[TMP] = ',';
    1876            0 :                 TMP = index(state.dataIPShortCut->cAlphaArgs(1), char(1));
    1877              :             }
    1878         5201 :             TMP = index(state.dataIPShortCut->cAlphaArgs(1), char(2));
    1879         5201 :             while (TMP != std::string::npos) {
    1880            0 :                 state.dataIPShortCut->cAlphaArgs(1)[TMP] = '!';
    1881            0 :                 TMP = index(state.dataIPShortCut->cAlphaArgs(1), char(2));
    1882              :             }
    1883              : 
    1884         5201 :             if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataHeatBalMgr->CurrentModuleObject, ErrorsFound)) {
    1885            0 :                 continue;
    1886              :             }
    1887              : 
    1888         5201 :             ++ZoneLoop;
    1889        15603 :             ProcessZoneData(state,
    1890              :                             cCurrentModuleObject,
    1891              :                             ZoneLoop,
    1892         5201 :                             state.dataIPShortCut->cAlphaArgs,
    1893              :                             NumAlphas,
    1894         5201 :                             state.dataIPShortCut->rNumericArgs,
    1895              :                             NumNumbers,
    1896         5201 :                             state.dataIPShortCut->lNumericFieldBlanks,
    1897         5201 :                             state.dataIPShortCut->lAlphaFieldBlanks,
    1898         5201 :                             state.dataIPShortCut->cAlphaFieldNames,
    1899         5201 :                             state.dataIPShortCut->cNumericFieldNames,
    1900              :                             ErrorsFound);
    1901              : 
    1902              :         } // Loop
    1903              : 
    1904         6002 :         for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1905              :             // Check to see if "nominally" controlled -- Zone Name appears in Zone Equip Configuration
    1906              :             // relies on zone name being the "name" of the Zone Controlled Equip Configuration
    1907        15603 :             if (state.dataInputProcessing->inputProcessor->getObjectItemNum(
    1908        10402 :                     state, "ZoneHVAC:EquipmentConnections", "zone_name", state.dataHeatBal->Zone(Loop).Name) > 0) {
    1909         4461 :                 state.dataHeatBal->Zone(Loop).isNominalControlled = true;
    1910              :             } else {
    1911          740 :                 state.dataHeatBal->Zone(Loop).isNominalControlled = false;
    1912              :             }
    1913              :         }
    1914              : 
    1915              :         // Get ZONE LIST objects
    1916          801 :         cCurrentModuleObject = "ZoneList";
    1917          801 :         state.dataHeatBal->NumOfZoneLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1918              : 
    1919          801 :         if (state.dataHeatBal->NumOfZoneLists > 0) {
    1920              : 
    1921           33 :             state.dataHeatBal->ZoneList.allocate(state.dataHeatBal->NumOfZoneLists);
    1922              : 
    1923           81 :             for (int ListNum = 1; ListNum <= state.dataHeatBal->NumOfZoneLists; ++ListNum) {
    1924           96 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1925              :                                                                          cCurrentModuleObject,
    1926              :                                                                          ListNum,
    1927           48 :                                                                          state.dataIPShortCut->cAlphaArgs,
    1928              :                                                                          NumAlphas,
    1929           48 :                                                                          state.dataIPShortCut->rNumericArgs,
    1930              :                                                                          NumNumbers,
    1931              :                                                                          IOStatus,
    1932           48 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    1933           48 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    1934           48 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    1935           48 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    1936              : 
    1937           48 :                 state.dataHeatBal->ZoneList(ListNum).Name = state.dataIPShortCut->cAlphaArgs(1);
    1938           48 :                 if (Util::FindItemInList(state.dataHeatBal->ZoneList(ListNum).Name, state.dataHeatBal->Zone) > 0) {
    1939            0 :                     ShowWarningError(
    1940              :                         state,
    1941            0 :                         format(
    1942            0 :                             "{}{}=\"{}\":  is a duplicate of a zone name.", RoutineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1943            0 :                     ShowContinueError(state, "This could be a problem in places where either a Zone Name or a Zone List can be used.");
    1944              :                 }
    1945              : 
    1946              :                 // List of zones
    1947           48 :                 state.dataHeatBal->ZoneList(ListNum).NumOfZones = NumAlphas - 1;
    1948              : 
    1949           48 :                 if (state.dataHeatBal->ZoneList(ListNum).NumOfZones < 1) {
    1950            0 :                     ShowSevereError(
    1951            0 :                         state, format("{}{}=\"{}\":  No zones specified.", RoutineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1952            0 :                     ErrorsFound = true;
    1953              :                 } else {
    1954           48 :                     state.dataHeatBal->ZoneList(ListNum).Zone.allocate(state.dataHeatBal->ZoneList(ListNum).NumOfZones);
    1955           48 :                     state.dataHeatBal->ZoneList(ListNum).Zone = 0;
    1956              : 
    1957          353 :                     for (ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(ListNum).NumOfZones; ++ZoneNum) {
    1958          305 :                         std::string ZoneName = state.dataIPShortCut->cAlphaArgs(ZoneNum + 1);
    1959          305 :                         state.dataHeatBal->ZoneList(ListNum).MaxZoneNameLength =
    1960          305 :                             max(state.dataHeatBal->ZoneList(ListNum).MaxZoneNameLength, len(ZoneName));
    1961          305 :                         state.dataHeatBal->ZoneList(ListNum).Zone(ZoneNum) = Util::FindItemInList(ZoneName, state.dataHeatBal->Zone);
    1962          305 :                         if (state.dataHeatBal->ZoneList(ListNum).Zone(ZoneNum) == 0) {
    1963            0 :                             ShowSevereError(state,
    1964            0 :                                             format("{}{}=\"{}\":  {} {} not found.",
    1965              :                                                    RoutineName,
    1966              :                                                    cCurrentModuleObject,
    1967            0 :                                                    state.dataIPShortCut->cAlphaArgs(1),
    1968            0 :                                                    state.dataIPShortCut->cAlphaFieldNames(ZoneNum + 1),
    1969              :                                                    ZoneName));
    1970            0 :                             ErrorsFound = true;
    1971              :                         }
    1972              : 
    1973              :                         // Check for duplicate zones
    1974         3810 :                         for (int Loop = 1; Loop <= ZoneNum - 1; ++Loop) {
    1975         3505 :                             if (state.dataHeatBal->ZoneList(ListNum).Zone(ZoneNum) == state.dataHeatBal->ZoneList(ListNum).Zone(Loop)) {
    1976            0 :                                 ShowSevereError(state,
    1977            0 :                                                 format("{}{}=\"{}\":  {} {} appears more than once in list.",
    1978              :                                                        RoutineName,
    1979              :                                                        cCurrentModuleObject,
    1980            0 :                                                        state.dataIPShortCut->cAlphaArgs(1),
    1981            0 :                                                        state.dataIPShortCut->cAlphaFieldNames(ZoneNum + 1),
    1982              :                                                        ZoneName));
    1983            0 :                                 ErrorsFound = true;
    1984              :                             }
    1985              :                         } // Loop
    1986          305 :                     } // ZoneNum
    1987              :                 }
    1988              : 
    1989              :             } // ListNum
    1990              :         }
    1991              : 
    1992              :         // Get ZONE GROUP objects
    1993          801 :         cCurrentModuleObject = "ZoneGroup";
    1994          801 :         state.dataHeatBal->NumOfZoneGroups = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1995              : 
    1996          801 :         if (state.dataHeatBal->NumOfZoneGroups > 0) {
    1997            2 :             state.dataHeatBal->ZoneGroup.allocate(state.dataHeatBal->NumOfZoneGroups);
    1998              : 
    1999            6 :             for (int GroupNum = 1; GroupNum <= state.dataHeatBal->NumOfZoneGroups; ++GroupNum) {
    2000            8 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2001              :                                                                          cCurrentModuleObject,
    2002              :                                                                          GroupNum,
    2003            4 :                                                                          state.dataIPShortCut->cAlphaArgs,
    2004              :                                                                          NumAlphas,
    2005            4 :                                                                          state.dataIPShortCut->rNumericArgs,
    2006              :                                                                          NumNumbers,
    2007              :                                                                          IOStatus,
    2008            4 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    2009            4 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    2010            4 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    2011            4 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    2012              : 
    2013            4 :                 state.dataHeatBal->ZoneGroup(GroupNum).Name = state.dataIPShortCut->cAlphaArgs(1);
    2014              : 
    2015              :                 // Multiplier - checked already by IDD rules
    2016            4 :                 state.dataHeatBal->ZoneGroup(GroupNum).Multiplier = state.dataIPShortCut->rNumericArgs(1);
    2017              : 
    2018              :                 // Zone list
    2019            4 :                 int ListNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->ZoneList);
    2020            4 :                 state.dataHeatBal->ZoneGroup(GroupNum).ZoneList = ListNum;
    2021              : 
    2022            4 :                 if (ListNum == 0) {
    2023            0 :                     ShowSevereError(state,
    2024            0 :                                     format("{}{}=\"{}\":  {} named {} not found.",
    2025              :                                            RoutineName,
    2026              :                                            cCurrentModuleObject,
    2027            0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    2028            0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
    2029            0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
    2030            0 :                     ErrorsFound = true;
    2031              :                 } else {
    2032              :                     // Check to make sure list is not in use by another ZONE GROUP
    2033            7 :                     for (int Loop = 1; Loop <= GroupNum - 1; ++Loop) {
    2034            3 :                         if (state.dataHeatBal->ZoneGroup(GroupNum).ZoneList == state.dataHeatBal->ZoneGroup(Loop).ZoneList) {
    2035            0 :                             ShowSevereError(state,
    2036            0 :                                             format("{}{}=\"{}\":  {} already used by {} named {}.",
    2037              :                                                    RoutineName,
    2038              :                                                    cCurrentModuleObject,
    2039            0 :                                                    state.dataIPShortCut->cAlphaArgs(1),
    2040            0 :                                                    state.dataIPShortCut->cAlphaFieldNames(2),
    2041              :                                                    cCurrentModuleObject,
    2042            0 :                                                    state.dataHeatBal->ZoneGroup(Loop).Name));
    2043            0 :                             ErrorsFound = true;
    2044              :                         }
    2045              :                     } // Loop
    2046              : 
    2047              :                     // Set group multiplier for each zone in the list
    2048           22 :                     for (int Loop = 1; Loop <= state.dataHeatBal->ZoneList(ListNum).NumOfZones; ++Loop) {
    2049           18 :                         ZoneNum = state.dataHeatBal->ZoneList(ListNum).Zone(Loop);
    2050              : 
    2051           18 :                         if (ZoneNum > 0) {
    2052              :                             // Check to make sure group multiplier was not already set by another ZONE GROUP
    2053           18 :                             if (state.dataHeatBal->Zone(ZoneNum).ListGroup == 0) {
    2054           18 :                                 state.dataHeatBal->Zone(ZoneNum).ListMultiplier = state.dataHeatBal->ZoneGroup(GroupNum).Multiplier;
    2055           18 :                                 state.dataHeatBal->Zone(ZoneNum).ListGroup = ListNum;
    2056              :                             } else {
    2057            0 :                                 ShowSevereError(state,
    2058            0 :                                                 format("{}{}=\"{}\":  Zone {} in ZoneList already exists in ZoneList of another ZoneGroup.",
    2059              :                                                        RoutineName,
    2060              :                                                        cCurrentModuleObject,
    2061            0 :                                                        state.dataIPShortCut->cAlphaArgs(1),
    2062            0 :                                                        state.dataHeatBal->Zone(ZoneNum).Name));
    2063            0 :                                 ShowContinueError(
    2064              :                                     state,
    2065            0 :                                     format("Previous ZoneList={}", state.dataHeatBal->ZoneList(state.dataHeatBal->Zone(ZoneNum).ListGroup).Name));
    2066            0 :                                 ErrorsFound = true;
    2067              :                             }
    2068              :                         }
    2069              :                     } // Loop
    2070              :                 }
    2071              : 
    2072              :             } // GroupNum
    2073              :         }
    2074              : 
    2075          801 :         GetZoneLocalEnvData(state, ErrorsFound);
    2076              : 
    2077              :         // allocate the array the holds the predefined report data
    2078          801 :         state.dataHeatBal->ZonePreDefRep.allocate(state.dataGlobal->NumOfZones);
    2079              : 
    2080              :         // Now get Space data after Zones are set up, because Space is optional, Zones are not
    2081          801 :         GetSpaceData(state, ErrorsFound);
    2082          801 :     }
    2083              : 
    2084          801 :     void GetIncidentSolarMultiplier(EnergyPlusData &state, bool &ErrorsFound)
    2085              :     {
    2086              :         static constexpr std::string_view RoutineName("GetIncidentSolarMultiplier: ");
    2087              :         static constexpr std::string_view routineName = "GetIncidentSolarMultiplier";
    2088              : 
    2089          801 :         auto &s_mat = state.dataMaterial;
    2090          801 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    2091          801 :         cCurrentModuleObject = "SurfaceProperty:IncidentSolarMultiplier";
    2092              : 
    2093          801 :         state.dataSurface->TotSurfIncSolMultiplier = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    2094              : 
    2095          801 :         if (state.dataSurface->TotSurfIncSolMultiplier <= 0) {
    2096          798 :             return;
    2097              :         }
    2098              : 
    2099            3 :         if (!allocated(state.dataSurface->SurfIncSolMultiplier)) {
    2100              :             // could be extended to interior surfaces later
    2101            3 :             state.dataSurface->SurfIncSolMultiplier.allocate(state.dataSurface->TotSurfaces);
    2102              :         }
    2103              : 
    2104              :         int NumAlpha;
    2105              :         int NumNumeric;
    2106              :         int IOStat;
    2107           14 :         for (int Loop = 1; Loop <= state.dataSurface->TotSurfIncSolMultiplier; ++Loop) {
    2108           22 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2109              :                                                                      cCurrentModuleObject,
    2110              :                                                                      Loop,
    2111           11 :                                                                      state.dataIPShortCut->cAlphaArgs,
    2112              :                                                                      NumAlpha,
    2113           11 :                                                                      state.dataIPShortCut->rNumericArgs,
    2114              :                                                                      NumNumeric,
    2115              :                                                                      IOStat,
    2116           11 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2117           11 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    2118           11 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2119           11 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2120              : 
    2121           11 :             ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
    2122              : 
    2123              :             // Assign surface number
    2124           11 :             int SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface);
    2125           11 :             if (SurfNum == 0) {
    2126            0 :                 ShowSevereError(state,
    2127            0 :                                 format("{}{}=\"{}, object. Illegal value for {} has been found.",
    2128              :                                        RoutineName,
    2129              :                                        cCurrentModuleObject,
    2130            0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    2131            0 :                                        state.dataIPShortCut->cAlphaFieldNames(1)));
    2132            0 :                 ShowContinueError(
    2133              :                     state,
    2134            0 :                     format("{} entered value = \"{}\" no corresponding surface (ref BuildingSurface:Detailed) has been found in the input file.",
    2135            0 :                            state.dataIPShortCut->cAlphaFieldNames(1),
    2136            0 :                            state.dataIPShortCut->cAlphaArgs(1)));
    2137            0 :                 ErrorsFound = true;
    2138            0 :                 continue;
    2139              :             }
    2140           11 :             auto &Surf = state.dataSurface->Surface(SurfNum);
    2141           11 :             if (Surf.Class != DataSurfaces::SurfaceClass::Window) {
    2142            0 :                 ShowSevereError(state, "IncidentSolarMultiplier defined for non-window surfaces");
    2143            0 :                 ErrorsFound = true;
    2144            0 :                 continue;
    2145              :             }
    2146           11 :             if (Surf.ExtBoundCond != DataSurfaces::ExternalEnvironment) {
    2147            0 :                 ShowSevereError(state, "IncidentSolarMultiplier defined for interior surfaces");
    2148            0 :                 ErrorsFound = true;
    2149            0 :                 continue;
    2150              :             }
    2151           11 :             int ConstrNum = Surf.Construction;
    2152           11 :             auto const &Constr = state.dataConstruction->Construct(ConstrNum);
    2153           11 :             auto const *mat = s_mat->materials(Constr.LayerPoint(Constr.TotLayers));
    2154           11 :             bool withNoncompatibleShades =
    2155           11 :                 (mat->group == Material::Group::Shade || mat->group == Material::Group::Blind || mat->group == Material::Group::Screen ||
    2156           11 :                  mat->group == Material::Group::GlassEQL || mat->group == Material::Group::WindowGapEQL || mat->group == Material::Group::ShadeEQL ||
    2157           33 :                  mat->group == Material::Group::DrapeEQL || mat->group == Material::Group::ScreenEQL || mat->group == Material::Group::BlindEQL ||
    2158           11 :                  Surf.HasShadeControl);
    2159           11 :             if (withNoncompatibleShades) {
    2160            0 :                 ShowSevereError(state, "Non-compatible shades defined alongside SurfaceProperty:IncidentSolarMultiplier for the same window");
    2161            0 :                 ErrorsFound = true;
    2162            0 :                 continue;
    2163              :             }
    2164              : 
    2165           11 :             Surf.hasIncSolMultiplier = true;
    2166           11 :             auto &SurfIncSolMult = state.dataSurface->SurfIncSolMultiplier(SurfNum);
    2167           11 :             SurfIncSolMult.Name = state.dataIPShortCut->cAlphaArgs(1);
    2168           11 :             SurfIncSolMult.SurfaceIdx = SurfNum;
    2169           11 :             SurfIncSolMult.Scaler = state.dataIPShortCut->rNumericArgs(1);
    2170              : 
    2171           11 :             if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    2172           11 :             } else if ((SurfIncSolMult.sched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(2))) == nullptr) {
    2173            0 :                 ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2));
    2174              :             }
    2175              :         } // for (Loop)
    2176              :     } // GetIncidentSolarMultiplier()
    2177              : 
    2178          801 :     void GetZoneLocalEnvData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
    2179              :     {
    2180              :         // SUBROUTINE INFORMATION:
    2181              :         //       AUTHOR         X LUO
    2182              :         //       DATE WRITTEN   July 2017
    2183              : 
    2184              :         // PURPOSE OF THIS SUBROUTINE:
    2185              :         // load input data for Outdoor Air Node for zones
    2186              : 
    2187              :         // Using/Aliasing
    2188              :         using DataLoopNode::ObjectIsParent;
    2189              :         using NodeInputManager::GetOnlySingleNode;
    2190              :         using OutAirNodeManager::CheckOutAirNodeNumber;
    2191              : 
    2192              :         //-----------------------------------------------------------------------
    2193              :         //               ZoneProperty:LocalEnvironment
    2194              :         //-----------------------------------------------------------------------
    2195          801 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    2196          801 :         cCurrentModuleObject = "ZoneProperty:LocalEnvironment";
    2197          801 :         int TotZoneEnv = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    2198              : 
    2199          801 :         if (TotZoneEnv > 0) {
    2200              :             int NumAlpha;
    2201              :             int NumNumeric;
    2202              :             int IOStat;
    2203            1 :             constexpr const char *RoutineName("GetZoneLocalEnvData: ");
    2204              :             // Check if IDD definition is correct
    2205            1 :             state.dataGlobal->AnyLocalEnvironmentsInModel = true;
    2206              : 
    2207            1 :             if (!allocated(state.dataHeatBal->ZoneLocalEnvironment)) {
    2208            1 :                 state.dataHeatBal->ZoneLocalEnvironment.allocate(TotZoneEnv);
    2209              :             }
    2210              : 
    2211            2 :             for (int Loop = 1; Loop <= TotZoneEnv; ++Loop) {
    2212            2 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2213              :                                                                          cCurrentModuleObject,
    2214              :                                                                          Loop,
    2215            1 :                                                                          state.dataIPShortCut->cAlphaArgs,
    2216              :                                                                          NumAlpha,
    2217            1 :                                                                          state.dataIPShortCut->rNumericArgs,
    2218              :                                                                          NumNumeric,
    2219              :                                                                          IOStat,
    2220            1 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    2221            1 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    2222            1 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    2223            1 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    2224              : 
    2225            1 :                 state.dataHeatBal->ZoneLocalEnvironment(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
    2226              : 
    2227              :                 // Assign zone number
    2228            1 :                 int ZoneNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
    2229            1 :                 if (ZoneNum == 0) {
    2230            0 :                     ShowSevereError(state,
    2231            0 :                                     format("{}{}=\"{}, object. Illegal value for {} has been found.",
    2232              :                                            RoutineName,
    2233              :                                            cCurrentModuleObject,
    2234            0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    2235            0 :                                            state.dataIPShortCut->cAlphaFieldNames(2)));
    2236            0 :                     ShowContinueError(state,
    2237            0 :                                       format("{} entered value = \"{}\" no corresponding zone has been found in the input file.",
    2238            0 :                                              state.dataIPShortCut->cAlphaFieldNames(2),
    2239            0 :                                              state.dataIPShortCut->cAlphaArgs(2)));
    2240            0 :                     ErrorsFound = true;
    2241              :                 } else {
    2242            1 :                     state.dataHeatBal->ZoneLocalEnvironment(Loop).ZonePtr = ZoneNum;
    2243              :                 }
    2244              : 
    2245              :                 // Assign outdoor air node number;
    2246            1 :                 int NodeNum = GetOnlySingleNode(state,
    2247            1 :                                                 state.dataIPShortCut->cAlphaArgs(3),
    2248              :                                                 ErrorsFound,
    2249              :                                                 DataLoopNode::ConnectionObjectType::ZonePropertyLocalEnvironment,
    2250            1 :                                                 state.dataIPShortCut->cAlphaArgs(1),
    2251              :                                                 DataLoopNode::NodeFluidType::Air,
    2252              :                                                 DataLoopNode::ConnectionType::Inlet,
    2253              :                                                 NodeInputManager::CompFluidStream::Primary,
    2254              :                                                 ObjectIsParent);
    2255            1 :                 if (NodeNum == 0 && CheckOutAirNodeNumber(state, NodeNum)) {
    2256            0 :                     ShowSevereError(state,
    2257            0 :                                     format("{}{}=\"{}, object. Illegal value for {} has been found.",
    2258              :                                            RoutineName,
    2259              :                                            cCurrentModuleObject,
    2260            0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    2261            0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
    2262            0 :                     ShowContinueError(state,
    2263            0 :                                       format("{} entered value = \"{}\" no corresponding schedule has been found in the input file.",
    2264            0 :                                              state.dataIPShortCut->cAlphaFieldNames(3),
    2265            0 :                                              state.dataIPShortCut->cAlphaArgs(3)));
    2266            0 :                     ErrorsFound = true;
    2267              :                 } else {
    2268            1 :                     state.dataHeatBal->ZoneLocalEnvironment(Loop).OutdoorAirNodePtr = NodeNum;
    2269              :                 }
    2270              :             }
    2271              :         }
    2272              :         // Link zone properties to zone object
    2273         6002 :         for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
    2274         5206 :             for (int Loop = 1; Loop <= TotZoneEnv; ++Loop) {
    2275            5 :                 if (state.dataHeatBal->ZoneLocalEnvironment(Loop).ZonePtr == ZoneLoop) {
    2276            1 :                     if (state.dataHeatBal->ZoneLocalEnvironment(Loop).OutdoorAirNodePtr != 0) {
    2277            1 :                         state.dataHeatBal->Zone(ZoneLoop).LinkedOutAirNode = state.dataHeatBal->ZoneLocalEnvironment(Loop).OutdoorAirNodePtr;
    2278              :                     }
    2279              :                 }
    2280              :             }
    2281              :         }
    2282          801 :     }
    2283              : 
    2284         5201 :     void ProcessZoneData(EnergyPlusData &state,
    2285              :                          std::string const &cCurrentModuleObject,
    2286              :                          int const ZoneLoop,
    2287              :                          Array1D_string const &cAlphaArgs,
    2288              :                          int const NumAlphas,
    2289              :                          Array1D<Real64> const &rNumericArgs,
    2290              :                          int const NumNumbers,
    2291              :                          [[maybe_unused]] Array1D_bool const &lNumericFieldBlanks, // Unused
    2292              :                          Array1D_bool const &lAlphaFieldBlanks,
    2293              :                          Array1D_string const &cAlphaFieldNames,
    2294              :                          [[maybe_unused]] Array1D_string const &cNumericFieldNames, // Unused
    2295              :                          bool &ErrorsFound                                          // If errors found in input
    2296              :     )
    2297              :     {
    2298              : 
    2299              :         // SUBROUTINE INFORMATION:
    2300              :         //       AUTHOR         Linda K. Lawrie
    2301              :         //       DATE WRITTEN   November 1997
    2302              :         //       MODIFIED       PGE: Added ZONE LIST and ZONE GROUP objects, Nov 2003
    2303              :         //                      RJH: Added init of DElight member of ZoneDaylight object, Jan 2004
    2304              :         //                      JG: Added Part of Total Floor Area field March 2006
    2305              :         //       RE-ENGINEERED  MJW: Split out processing zone input to facilitate unit testing, Nov 2014
    2306              : 
    2307              :         // PURPOSE OF THIS SUBROUTINE:
    2308              :         // This subroutine gets the zone data for each zone in the input file.
    2309              : 
    2310         5201 :         constexpr const char *RoutineName("ProcessZoneData: ");
    2311              : 
    2312         5201 :         state.dataHeatBal->Zone(ZoneLoop).Name = cAlphaArgs(1);
    2313         5201 :         if (NumNumbers >= 1) {
    2314         5201 :             state.dataHeatBal->Zone(ZoneLoop).RelNorth = rNumericArgs(1);
    2315              :         }
    2316         5201 :         if (NumNumbers >= 2) {
    2317         5201 :             state.dataHeatBal->Zone(ZoneLoop).OriginX = rNumericArgs(2);
    2318              :         }
    2319         5201 :         if (NumNumbers >= 3) {
    2320         5201 :             state.dataHeatBal->Zone(ZoneLoop).OriginY = rNumericArgs(3);
    2321              :         }
    2322         5201 :         if (NumNumbers >= 4) {
    2323         5201 :             state.dataHeatBal->Zone(ZoneLoop).OriginZ = rNumericArgs(4);
    2324              :         }
    2325         5201 :         if (NumNumbers >= 5) {
    2326         5144 :             state.dataHeatBal->Zone(ZoneLoop).OfType = rNumericArgs(5);
    2327              :         }
    2328         5201 :         state.dataHeatBal->Zone(ZoneLoop).OfType = DataHeatBalance::StandardZone;
    2329         5201 :         if (NumNumbers >= 6) {
    2330         5144 :             state.dataHeatBal->Zone(ZoneLoop).Multiplier = rNumericArgs(6);
    2331              :         }
    2332         5201 :         if (NumNumbers >= 7) {
    2333         5004 :             state.dataHeatBal->Zone(ZoneLoop).CeilingHeight = rNumericArgs(7);
    2334              :         }
    2335         5201 :         if (NumNumbers >= 8) {
    2336         4978 :             state.dataHeatBal->Zone(ZoneLoop).Volume = rNumericArgs(8);
    2337              :         }
    2338         5201 :         if (NumNumbers >= 9) {
    2339         2530 :             state.dataHeatBal->Zone(ZoneLoop).UserEnteredFloorArea = rNumericArgs(9);
    2340              :         }
    2341              : 
    2342         5201 :         if (NumAlphas > 1 && !state.dataIPShortCut->lAlphaFieldBlanks(2)) {
    2343           95 :             Convect::HcInt hcIn = static_cast<Convect::HcInt>(getEnumValue(Convect::HcIntNamesUC, cAlphaArgs(2)));
    2344              : 
    2345           95 :             if (hcIn != Convect::HcInt::ASHRAESimple && hcIn != Convect::HcInt::ASHRAETARP && hcIn != Convect::HcInt::CeilingDiffuser &&
    2346            1 :                 hcIn != Convect::HcInt::TrombeWall && hcIn != Convect::HcInt::AdaptiveConvectionAlgorithm && hcIn != Convect::HcInt::ASTMC1340) {
    2347              : 
    2348            0 :                 ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, cCurrentModuleObject, state.dataHeatBal->Zone(ZoneLoop).Name));
    2349            0 :                 ShowContinueError(state, format("Invalid value for {}=\"{}\".", cAlphaFieldNames(2), cAlphaArgs(2)));
    2350            0 :                 ErrorsFound = true;
    2351              :             }
    2352           95 :             state.dataHeatBal->Zone(ZoneLoop).IntConvAlgo = hcIn;
    2353              :         } else {
    2354              :             // No zone specific algorithm specified, use default Inside Convection Algorithm
    2355         5106 :             state.dataHeatBal->Zone(ZoneLoop).IntConvAlgo = state.dataHeatBal->DefaultIntConvAlgo;
    2356              :         }
    2357              : 
    2358         5201 :         if (NumAlphas > 2 && !state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    2359              : 
    2360           15 :             Convect::HcExt hcOut = static_cast<Convect::HcExt>(getEnumValue(Convect::HcExtNamesUC, cAlphaArgs(3)));
    2361              : 
    2362           15 :             if (hcOut != Convect::HcExt::ASHRAESimple && hcOut != Convect::HcExt::ASHRAETARP && hcOut != Convect::HcExt::MoWiTTHcOutside &&
    2363            2 :                 hcOut != Convect::HcExt::DOE2HcOutside && hcOut != Convect::HcExt::AdaptiveConvectionAlgorithm) {
    2364              : 
    2365            0 :                 ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, cCurrentModuleObject, state.dataHeatBal->Zone(ZoneLoop).Name));
    2366            0 :                 ShowContinueError(state, format("Invalid value for {}=\"{}\".", cAlphaFieldNames(3), cAlphaArgs(3)));
    2367            0 :                 ErrorsFound = true;
    2368              :             }
    2369           15 :             state.dataHeatBal->Zone(ZoneLoop).ExtConvAlgo = hcOut;
    2370              : 
    2371              :         } else {
    2372              :             // No zone specific algorithm specified, use default Outside Convection Algorithm
    2373         5186 :             state.dataHeatBal->Zone(ZoneLoop).ExtConvAlgo = state.dataHeatBal->DefaultExtConvAlgo;
    2374              :         }
    2375              : 
    2376              :         // Process the input field:    Part of Total Floor Area
    2377              :         //   The default value is YES and so only NO needs to be handled
    2378         5201 :         if (NumAlphas > 3) {
    2379         2428 :             if (Util::SameString("No", cAlphaArgs(4))) {
    2380          148 :                 state.dataHeatBal->Zone(ZoneLoop).isPartOfTotalArea = false;
    2381         2280 :             } else if (Util::SameString("Yes", cAlphaArgs(4)) || lAlphaFieldBlanks(4)) {
    2382         2280 :                 state.dataHeatBal->Zone(ZoneLoop).isPartOfTotalArea = true;
    2383              :             } else {
    2384            0 :                 ShowSevereError(state, format("{}{}=\"{}\".", RoutineName, cCurrentModuleObject, state.dataHeatBal->Zone(ZoneLoop).Name));
    2385            0 :                 ShowContinueError(state, format("Invalid value for {}=\"{}\".", cAlphaFieldNames(4), cAlphaArgs(4)));
    2386            0 :                 ErrorsFound = true;
    2387              :             }
    2388              :         }
    2389              : 
    2390              :         // Zone outdoor environmental variables, used for zone infiltration/ventilation
    2391        10402 :         SetupOutputVariable(state,
    2392              :                             "Zone Outdoor Air Drybulb Temperature",
    2393              :                             Constant::Units::C,
    2394         5201 :                             state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp,
    2395              :                             OutputProcessor::TimeStepType::Zone,
    2396              :                             OutputProcessor::StoreType::Average,
    2397         5201 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    2398        10402 :         SetupOutputVariable(state,
    2399              :                             "Zone Outdoor Air Wetbulb Temperature",
    2400              :                             Constant::Units::C,
    2401         5201 :                             state.dataHeatBal->Zone(ZoneLoop).OutWetBulbTemp,
    2402              :                             OutputProcessor::TimeStepType::Zone,
    2403              :                             OutputProcessor::StoreType::Average,
    2404         5201 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    2405        10402 :         SetupOutputVariable(state,
    2406              :                             "Zone Outdoor Air Wind Speed",
    2407              :                             Constant::Units::m_s,
    2408         5201 :                             state.dataHeatBal->Zone(ZoneLoop).WindSpeed,
    2409              :                             OutputProcessor::TimeStepType::Zone,
    2410              :                             OutputProcessor::StoreType::Average,
    2411         5201 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    2412        10402 :         SetupOutputVariable(state,
    2413              :                             "Zone Outdoor Air Wind Direction",
    2414              :                             Constant::Units::deg,
    2415         5201 :                             state.dataHeatBal->Zone(ZoneLoop).WindDir,
    2416              :                             OutputProcessor::TimeStepType::Zone,
    2417              :                             OutputProcessor::StoreType::Average,
    2418         5201 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    2419         5201 :     }
    2420              : 
    2421          801 :     void GetSpaceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    2422              :     {
    2423          801 :         constexpr const char *RoutineName("GetSpaceData: ");
    2424          801 :         std::string cCurrentModuleObject = "Space";
    2425          801 :         auto &ip = state.dataInputProcessing->inputProcessor;
    2426          801 :         auto const instances = ip->epJSON.find(cCurrentModuleObject);
    2427          801 :         if (instances != ip->epJSON.end()) {
    2428            6 :             auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
    2429            6 :             auto &instancesValue = instances.value();
    2430            6 :             int numSpaces = instancesValue.size();
    2431            6 :             int spaceNum = 0;
    2432              :             // Allow for one additional Space per zone if some surfaces do not have a Space assigned in input
    2433            6 :             state.dataHeatBal->space.allocate(size_t(numSpaces + state.dataGlobal->NumOfZones));
    2434              :             // Allow for one additional "General" space type for auto-generated spaces
    2435            6 :             state.dataHeatBal->spaceTypes.allocate(size_t(numSpaces + 1));
    2436              : 
    2437           35 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    2438           29 :                 ++spaceNum;
    2439           29 :                 auto const &objectFields = instance.value();
    2440           29 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    2441           29 :                 thisSpace.Name = Util::makeUPPER(instance.key());
    2442           29 :                 ip->markObjectAsUsed(cCurrentModuleObject, instance.key());
    2443           58 :                 std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
    2444           58 :                 thisSpace.CeilingHeight = ip->getRealFieldValue(objectFields, objectSchemaProps, "ceiling_height");
    2445           58 :                 thisSpace.Volume = ip->getRealFieldValue(objectFields, objectSchemaProps, "volume");
    2446           58 :                 thisSpace.userEnteredFloorArea = ip->getRealFieldValue(objectFields, objectSchemaProps, "floor_area");
    2447           29 :                 int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
    2448           29 :                 if (zoneNum > 0) {
    2449           29 :                     thisSpace.zoneNum = zoneNum;
    2450           29 :                     state.dataHeatBal->Zone(zoneNum).spaceIndexes.emplace_back(spaceNum);
    2451           29 :                     ++state.dataHeatBal->Zone(zoneNum).numSpaces;
    2452              :                 } else {
    2453            0 :                     ShowSevereError(state, format("{}{}={}", RoutineName, cCurrentModuleObject, thisSpace.Name));
    2454            0 :                     ShowContinueError(state, format("Zone Name ={}not found.", zoneName));
    2455            0 :                     ErrorsFound = true;
    2456              :                 }
    2457           58 :                 thisSpace.spaceType = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "space_type");
    2458           29 :                 bool spaceTypeFound = false;
    2459           48 :                 for (int spaceTypePtr = 1; spaceTypePtr <= state.dataGlobal->numSpaceTypes; ++spaceTypePtr) {
    2460           32 :                     if (Util::SameString(thisSpace.spaceType, state.dataHeatBal->spaceTypes(spaceTypePtr))) {
    2461           13 :                         thisSpace.spaceTypeNum = spaceTypePtr;
    2462           13 :                         spaceTypeFound = true;
    2463           13 :                         break;
    2464              :                     }
    2465              :                 }
    2466           29 :                 if (!spaceTypeFound) {
    2467           16 :                     ++state.dataGlobal->numSpaceTypes;
    2468           16 :                     state.dataHeatBal->spaceTypes(state.dataGlobal->numSpaceTypes) = thisSpace.spaceType;
    2469           16 :                     thisSpace.spaceTypeNum = state.dataGlobal->numSpaceTypes;
    2470              :                 }
    2471              : 
    2472           29 :                 auto extensibles = objectFields.find("tags");
    2473           29 :                 auto const &extensionSchemaProps = objectSchemaProps["tags"]["items"]["properties"];
    2474           29 :                 if (extensibles != objectFields.end()) {
    2475           24 :                     auto &extensiblesArray = extensibles.value();
    2476           72 :                     for (auto &extensibleInstance : extensiblesArray) {
    2477          144 :                         thisSpace.tags.emplace_back(ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "tag"));
    2478           24 :                     }
    2479              :                 }
    2480           35 :             }
    2481            6 :             state.dataGlobal->numSpaces = spaceNum;
    2482              :         } else {
    2483              :             // If no Spaces are defined, then allow for one Space per zone, and one spaceType
    2484          795 :             state.dataHeatBal->space.allocate(state.dataGlobal->NumOfZones);
    2485          795 :             state.dataHeatBal->spaceTypes.allocate(1);
    2486              :         }
    2487              : 
    2488          801 :         cCurrentModuleObject = "SpaceList";
    2489          801 :         auto const instances2 = ip->epJSON.find(cCurrentModuleObject);
    2490          801 :         if (instances2 != ip->epJSON.end()) {
    2491            5 :             auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
    2492            5 :             auto &instancesValue = instances2.value();
    2493            5 :             int numSpaceLists = instancesValue.size();
    2494            5 :             int spaceListNum = 0;
    2495            5 :             state.dataHeatBal->spaceList.allocate(numSpaceLists);
    2496           10 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    2497            5 :                 ++spaceListNum;
    2498            5 :                 auto const &objectFields = instance.value();
    2499            5 :                 auto &thisSpaceList = state.dataHeatBal->spaceList(spaceListNum);
    2500            5 :                 thisSpaceList.Name = Util::makeUPPER(instance.key());
    2501            5 :                 ip->markObjectAsUsed(cCurrentModuleObject, instance.key());
    2502              : 
    2503            5 :                 if (Util::FindItemInList(thisSpaceList.Name, state.dataHeatBal->Zone) > 0) {
    2504            0 :                     ShowSevereError(state,
    2505            0 :                                     format("{}{}=\"{}\":  is a duplicate of a zone name.", RoutineName, cCurrentModuleObject, thisSpaceList.Name));
    2506            0 :                     ErrorsFound = true;
    2507              :                 }
    2508            5 :                 if (Util::FindItemInList(thisSpaceList.Name, state.dataHeatBal->space) > 0) {
    2509            0 :                     ShowSevereError(state,
    2510            0 :                                     format("{}{}=\"{}\":  is a duplicate of a space name.", RoutineName, cCurrentModuleObject, thisSpaceList.Name));
    2511            0 :                     ErrorsFound = true;
    2512              :                 }
    2513              : 
    2514              :                 // List of spaces
    2515            5 :                 thisSpaceList.numListSpaces = 0;
    2516            5 :                 auto extensibles = objectFields.find("spaces");
    2517            5 :                 auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
    2518            5 :                 if (extensibles != objectFields.end()) {
    2519            5 :                     auto &extensiblesArray = extensibles.value();
    2520           31 :                     for (auto &extensibleInstance : extensiblesArray) {
    2521           52 :                         std::string thisSpaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
    2522           26 :                         int thisSpaceNum = Util::FindItemInList(thisSpaceName, state.dataHeatBal->space);
    2523           26 :                         if (thisSpaceNum > 0) {
    2524           26 :                             thisSpaceList.spaces.emplace_back(thisSpaceNum);
    2525           26 :                             ++thisSpaceList.numListSpaces;
    2526              :                         } else {
    2527            0 :                             ShowSevereError(state, format("{}{}={}", RoutineName, cCurrentModuleObject, thisSpaceList.Name));
    2528            0 :                             ShowContinueError(state, format("Space Name={} not found.", thisSpaceName));
    2529            0 :                             ErrorsFound = true;
    2530              :                         }
    2531           26 :                         thisSpaceList.maxSpaceNameLength = max(thisSpaceList.maxSpaceNameLength, len(thisSpaceName));
    2532              :                         // Check for duplicate spaces
    2533          110 :                         for (int loop = 1; loop <= int(thisSpaceList.spaces.size()) - 1; ++loop) {
    2534           84 :                             if (thisSpaceNum == thisSpaceList.spaces(loop)) {
    2535            0 :                                 ShowSevereError(state,
    2536            0 :                                                 format("{}{}=\"{}\":  Space Name {} appears more than once in list.",
    2537              :                                                        RoutineName,
    2538              :                                                        cCurrentModuleObject,
    2539            0 :                                                        thisSpaceList.Name,
    2540              :                                                        thisSpaceName));
    2541            0 :                                 ErrorsFound = true;
    2542              :                             }
    2543              :                         }
    2544           31 :                     }
    2545              :                 }
    2546           10 :             }
    2547              :         }
    2548              : 
    2549              :         // Make sure every zone has at least one space
    2550         6002 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2551         5201 :             auto &thisZone = state.dataHeatBal->Zone(zoneNum);
    2552         5201 :             if (thisZone.spaceIndexes.empty()) {
    2553         5181 :                 ++state.dataGlobal->numSpaces;
    2554         5181 :                 state.dataHeatBal->space(state.dataGlobal->numSpaces).zoneNum = zoneNum;
    2555         5181 :                 state.dataHeatBal->space(state.dataGlobal->numSpaces).Name = thisZone.Name;
    2556         5181 :                 state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceType = "GENERAL";
    2557         5181 :                 state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceTypeNum = GetGeneralSpaceTypeNum(state);
    2558              :                 // Add to zone's list of spaces
    2559         5181 :                 thisZone.spaceIndexes.emplace_back(state.dataGlobal->numSpaces);
    2560         5181 :                 ++state.dataHeatBal->Zone(zoneNum).numSpaces;
    2561              :             }
    2562              :         }
    2563          801 :     }
    2564              : 
    2565         5184 :     int GetGeneralSpaceTypeNum(EnergyPlusData &state)
    2566              :     {
    2567              :         // If "General" exists as a space type return the index
    2568         5184 :         bool generalSpaceTypeExists = false;
    2569         5184 :         int generalSpaceTypeNum = 0;
    2570         5208 :         for (int spaceTypePtr = 1; spaceTypePtr <= state.dataGlobal->numSpaceTypes; ++spaceTypePtr) {
    2571         4442 :             if (Util::SameString(state.dataHeatBal->spaceTypes(spaceTypePtr), "GENERAL")) {
    2572         4418 :                 generalSpaceTypeNum = spaceTypePtr;
    2573         4418 :                 generalSpaceTypeExists = true;
    2574         4418 :                 break;
    2575              :             }
    2576              :         }
    2577              :         // Add General space type if it doesn't exist yet
    2578         5184 :         if (!generalSpaceTypeExists) {
    2579          766 :             ++state.dataGlobal->numSpaceTypes;
    2580          766 :             state.dataHeatBal->spaceTypes(state.dataGlobal->numSpaceTypes) = "GENERAL";
    2581          766 :             generalSpaceTypeNum = state.dataGlobal->numSpaceTypes;
    2582              :         }
    2583         5184 :         return generalSpaceTypeNum;
    2584              :     }
    2585              :     // End of Get Input subroutines for the HB Module
    2586              :     //******************************************************************************
    2587              : 
    2588              :     // Beginning Initialization Section of the Module
    2589              :     //******************************************************************************
    2590              : 
    2591      2828212 :     void InitHeatBalance(EnergyPlusData &state)
    2592              :     {
    2593              : 
    2594              :         // SUBROUTINE INFORMATION:
    2595              :         //       AUTHOR         Rick Strand
    2596              :         //       DATE WRITTEN   April 1997
    2597              : 
    2598              :         // PURPOSE OF THIS SUBROUTINE:
    2599              :         // This subroutine is the main driver for initializations within the
    2600              :         // heat balance.
    2601              : 
    2602              :         // METHODOLOGY EMPLOYED:
    2603              :         // Uses the status flags to trigger initialization events.  Some of the files
    2604              :         //  have been moved to other heat balance managers.  More of these initializations
    2605              :         //  will have to continue to be re-structured.
    2606              : 
    2607              :         // Using/Aliasing
    2608              :         using namespace Window;
    2609              :         using namespace SolarShading;
    2610              :         using Dayltg::InitDaylightingDevices;
    2611              :         using OutAirNodeManager::SetOutAirNodes;
    2612              :         using WindowEquivalentLayer::InitEquivalentLayerWindowCalculations;
    2613              : 
    2614      2828212 :         if (state.dataGlobal->BeginSimFlag) {
    2615          801 :             AllocateHeatBalArrays(state); // Allocate the Module Arrays
    2616          801 :             if (state.dataHeatBal->AnyCTF || state.dataHeatBal->AnyEMPD) {
    2617          788 :                 DisplayString(state, "Initializing Response Factors");
    2618          788 :                 InitConductionTransferFunctions(state); // Initialize the response factors
    2619              :             }
    2620          801 :             HeatBalanceSurfaceManager::InitSurfacePropertyViewFactors(state);
    2621          801 :             DisplayString(state, "Initializing Window Optical Properties");
    2622          801 :             InitEquivalentLayerWindowCalculations(state); // Initialize the EQL window optical properties
    2623              :             // InitGlassOpticalCalculations(); // Initialize the window optical properties
    2624          801 :             Window::InitWindowOpticalCalculations(state);
    2625          801 :             InitDaylightingDevices(state); // Initialize any daylighting devices
    2626          801 :             DisplayString(state, "Initializing Solar Calculations");
    2627          801 :             InitSolarCalculations(state); // Initialize the shadowing calculations
    2628              :         }
    2629              : 
    2630      2828212 :         if (state.dataGlobal->BeginEnvrnFlag) {
    2631         6496 :             state.dataHeatBalMgr->MaxHeatLoadPrevDay = 0.0;
    2632         6496 :             state.dataHeatBalMgr->MaxCoolLoadPrevDay = 0.0;
    2633         6496 :             state.dataHeatBalMgr->MaxTempPrevDay = 0.0;
    2634         6496 :             state.dataHeatBalMgr->MinTempPrevDay = 0.0;
    2635         6496 :             state.dataHeatBalMgr->MaxHeatLoadZone = -9999.0;
    2636         6496 :             state.dataHeatBalMgr->MaxCoolLoadZone = -9999.0;
    2637         6496 :             state.dataHeatBalMgr->MaxTempZone = -9999.0;
    2638         6496 :             state.dataHeatBalMgr->MinTempZone = 1000.0;
    2639         6496 :             state.dataHeatBalMgr->TempZone = -9999.0;
    2640         6496 :             state.dataHeatBalMgr->LoadZone = -9999.0;
    2641         6496 :             state.dataHeatBalMgr->TempZonePrevDay = 1000.0;
    2642         6496 :             state.dataHeatBalMgr->LoadZonePrevDay = -9999.0;
    2643         6496 :             state.dataHeatBalMgr->TempZoneSecPrevDay = -9999.0;
    2644         6496 :             state.dataHeatBalMgr->WarmupTempDiff = 0.0;
    2645         6496 :             state.dataHeatBalMgr->WarmupLoadDiff = 0.0;
    2646         6496 :             state.dataHeatBalMgr->TempZoneRpt = 0.0;
    2647         6496 :             state.dataHeatBalMgr->LoadZoneRpt = 0.0;
    2648         6496 :             state.dataHeatBalMgr->MaxLoadZoneRpt = 0.0;
    2649         6496 :             state.dataHeatBalMgr->CountWarmupDayPoints = 0;
    2650              : 
    2651       465042 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
    2652       917092 :                 std::fill(
    2653       458546 :                     state.dataSurface->SurfaceWindow(SurfNum).thetaFace.begin(), state.dataSurface->SurfaceWindow(SurfNum).thetaFace.end(), 296.15);
    2654       458546 :                 state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) = 23.0;
    2655              :             }
    2656              :         }
    2657              : 
    2658      2828212 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    2659       421444 :             HeatBalanceSurfaceManager::InitEMSControlledConstructions(state);
    2660       421444 :             HeatBalanceSurfaceManager::InitEMSControlledSurfaceProperties(state);
    2661              :         }
    2662              : 
    2663              :         // Init storm window pointers
    2664      2828212 :         if (state.dataSurface->TotStormWin > 0) {
    2665         2022 :             if (state.dataGlobal->BeginDayFlag) {
    2666           16 :                 SetStormWindowControl(state);
    2667           16 :                 state.dataHeatBalMgr->ChangeSet = false;
    2668         2006 :             } else if (!state.dataHeatBalMgr->ChangeSet) {
    2669           16 :                 state.dataHeatBal->StormWinChangeThisDay = false;
    2670           32 :                 for (int StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
    2671           16 :                     int SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum;
    2672           16 :                     state.dataSurface->SurfWinStormWinFlagPrevDay(SurfNum) = state.dataSurface->SurfWinStormWinFlag(SurfNum);
    2673              :                 }
    2674           16 :                 state.dataHeatBalMgr->ChangeSet = true;
    2675              :             }
    2676         8088 :             for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2677        12132 :                 for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2678         6066 :                     auto const &thisSpace = state.dataHeatBal->space(spaceNum);
    2679         6066 :                     int const firstSurfWin = thisSpace.WindowSurfaceFirst;
    2680         6066 :                     int const lastSurfWin = thisSpace.WindowSurfaceLast;
    2681         8088 :                     for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
    2682         3033 :                         if (state.dataSurface->SurfWinStormWinFlag(SurfNum) == 1 &&
    2683         1011 :                             state.dataSurface->SurfWinWindowModelType(SurfNum) == DataSurfaces::WindowModel::Detailed) {
    2684         1011 :                             state.dataSurface->SurfActiveConstruction(SurfNum) = state.dataSurface->SurfWinStormWinConstr(SurfNum);
    2685              :                         } else {
    2686         1011 :                             state.dataSurface->SurfActiveConstruction(SurfNum) = state.dataSurface->Surface(SurfNum).Construction;
    2687              :                         }
    2688              :                     }
    2689         6066 :                 }
    2690              :             }
    2691              :         }
    2692              : 
    2693      2828212 :         if (state.dataGlobal->BeginSimFlag && state.dataGlobal->DoWeathSim && state.dataSysVars->ReportExtShadingSunlitFrac) {
    2694            0 :             OpenShadingFile(state);
    2695              :         }
    2696              : 
    2697      2828212 :         if (state.dataGlobal->BeginDayFlag) {
    2698        25938 :             if (!state.dataGlobal->WarmupFlag) {
    2699         5261 :                 if (state.dataGlobal->DayOfSim == 1) {
    2700         2646 :                     state.dataHeatBalMgr->MaxHeatLoadZone = -9999.0;
    2701         2646 :                     state.dataHeatBalMgr->MaxCoolLoadZone = -9999.0;
    2702         2646 :                     state.dataHeatBalMgr->MaxTempZone = -9999.0;
    2703         2646 :                     state.dataHeatBalMgr->MinTempZone = 1000.0;
    2704              :                 }
    2705              :             }
    2706        25938 :             if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    2707        25872 :                 PerformSolarCalculations(state);
    2708              :             }
    2709              :         }
    2710              : 
    2711      2828212 :         if (state.dataSysVars->DetailedSolarTimestepIntegration) { // always redo solar calcs
    2712         8094 :             PerformSolarCalculations(state);
    2713              :         }
    2714              : 
    2715      2830768 :         if (state.dataGlobal->BeginDayFlag && !state.dataGlobal->WarmupFlag && state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather &&
    2716         2556 :             state.dataSysVars->ReportExtShadingSunlitFrac) {
    2717            0 :             for (int iHour = 1; iHour <= Constant::iHoursInDay; ++iHour) { // Do for all hours.
    2718            0 :                 for (int TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
    2719            0 :                     constexpr const char *ShdFracFmt1(" {:02}/{:02} {:02}:{:02},");
    2720            0 :                     if (TS == state.dataGlobal->TimeStepsInHour) {
    2721            0 :                         print(state.files.shade, ShdFracFmt1, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth, iHour, 0);
    2722              :                     } else {
    2723            0 :                         print(state.files.shade,
    2724              :                               ShdFracFmt1,
    2725            0 :                               state.dataEnvrn->Month,
    2726            0 :                               state.dataEnvrn->DayOfMonth,
    2727            0 :                               iHour - 1,
    2728            0 :                               (60 / state.dataGlobal->TimeStepsInHour) * TS);
    2729              :                     }
    2730            0 :                     for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2731            0 :                         constexpr const char *ShdFracFmt2("{:10.8F},");
    2732            0 :                         print(state.files.shade, ShdFracFmt2, state.dataHeatBal->SurfSunlitFrac(iHour, TS, SurfNum));
    2733              :                     }
    2734            0 :                     print(state.files.shade, "\n");
    2735              :                 }
    2736              :             }
    2737              :         }
    2738              : 
    2739              :         // Initialize zone outdoor environmental variables
    2740              :         // Bulk Initialization for Temperatures & WindSpeed
    2741              :         // using the zone, modify the zone  Dry/Wet BulbTemps
    2742      2828212 :         DataHeatBalance::SetZoneOutBulbTempAt(state);
    2743      2828212 :         DataHeatBalance::CheckZoneOutBulbTempAt(state);
    2744              : 
    2745              :         // set zone level wind dir to global value
    2746      2828212 :         DataHeatBalance::SetZoneWindSpeedAt(state);
    2747      2828212 :         DataHeatBalance::SetZoneWindDirAt(state);
    2748              : 
    2749              :         // Set zone data to linked air node value if defined.
    2750      2828212 :         if (state.dataGlobal->AnyLocalEnvironmentsInModel) {
    2751         7436 :             SetOutAirNodes(state);
    2752        45980 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2753        38544 :                 if (state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode > 0) {
    2754         1353 :                     if (state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirDryBulbSched != nullptr) {
    2755         1353 :                         state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp =
    2756         1353 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirDryBulbSched->getCurrentVal();
    2757              :                     } else {
    2758            0 :                         state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp =
    2759            0 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).OutAirDryBulb;
    2760              :                     }
    2761         1353 :                     if (state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirWetBulbSched != nullptr) {
    2762         1353 :                         state.dataHeatBal->Zone(ZoneNum).OutWetBulbTemp =
    2763         1353 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirWetBulbSched->getCurrentVal();
    2764              :                     } else {
    2765            0 :                         state.dataHeatBal->Zone(ZoneNum).OutWetBulbTemp =
    2766            0 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).OutAirWetBulb;
    2767              :                     }
    2768         1353 :                     if (state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirWindSpeedSched != nullptr) {
    2769         1353 :                         state.dataHeatBal->Zone(ZoneNum).WindSpeed =
    2770         1353 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirWindSpeedSched->getCurrentVal();
    2771              :                     } else {
    2772            0 :                         state.dataHeatBal->Zone(ZoneNum).WindSpeed =
    2773            0 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).OutAirWindSpeed;
    2774              :                     }
    2775         1353 :                     if (state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirWindDirSched != nullptr) {
    2776         1353 :                         state.dataHeatBal->Zone(ZoneNum).WindDir =
    2777         1353 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).outAirWindDirSched->getCurrentVal();
    2778              :                     } else {
    2779            0 :                         state.dataHeatBal->Zone(ZoneNum).WindDir =
    2780            0 :                             state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).LinkedOutAirNode).OutAirWindDir;
    2781              :                     }
    2782              :                 }
    2783              :             }
    2784              :         }
    2785              : 
    2786              :         // Overwriting surface and zone level environmental data with EMS override value
    2787      2828212 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    2788      5432173 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2789      5010729 :                 if (state.dataHeatBal->Zone(ZoneNum).OutDryBulbTempEMSOverrideOn) {
    2790            0 :                     state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp = state.dataHeatBal->Zone(ZoneNum).OutDryBulbTempEMSOverrideValue;
    2791              :                 }
    2792      5010729 :                 if (state.dataHeatBal->Zone(ZoneNum).OutWetBulbTempEMSOverrideOn) {
    2793            0 :                     state.dataHeatBal->Zone(ZoneNum).OutWetBulbTemp = state.dataHeatBal->Zone(ZoneNum).OutWetBulbTempEMSOverrideValue;
    2794              :                 }
    2795      5010729 :                 if (state.dataHeatBal->Zone(ZoneNum).WindSpeedEMSOverrideOn) {
    2796            0 :                     state.dataHeatBal->Zone(ZoneNum).WindSpeed = state.dataHeatBal->Zone(ZoneNum).WindSpeedEMSOverrideValue;
    2797              :                 }
    2798      5010729 :                 if (state.dataHeatBal->Zone(ZoneNum).WindDirEMSOverrideOn) {
    2799            0 :                     state.dataHeatBal->Zone(ZoneNum).WindDir = state.dataHeatBal->Zone(ZoneNum).WindDirEMSOverrideValue;
    2800              :                 }
    2801              :             }
    2802              :         }
    2803              : 
    2804      2828212 :         if (state.dataGlobal->BeginSimFlag) {
    2805         6002 :             for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2806        10414 :                 for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    2807         5213 :                     auto const &thisSpace = state.dataHeatBal->space(spaceNum);
    2808         5213 :                     int const firstSurfWin = thisSpace.WindowSurfaceFirst;
    2809         5213 :                     int const lastSurfWin = thisSpace.WindowSurfaceLast;
    2810        11572 :                     for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
    2811        12694 :                         if (state.dataSurface->SurfWinWindowModelType(SurfNum) != DataSurfaces::WindowModel::BSDF &&
    2812         6335 :                             state.dataSurface->SurfWinWindowModelType(SurfNum) != DataSurfaces::WindowModel::EQL) {
    2813         6332 :                             state.dataSurface->SurfWinWindowModelType(SurfNum) = DataSurfaces::WindowModel::Detailed;
    2814              :                         }
    2815              :                     }
    2816         5201 :                 }
    2817              :             }
    2818              :         }
    2819      2828212 :     }
    2820              : 
    2821          801 :     void AllocateZoneHeatBalArrays(EnergyPlusData &state)
    2822              :     {
    2823              :         // Allocate zone / encl hb arrays
    2824              : 
    2825              :         // TODO MJW: Punt for now, sometimes unit test will get here and need these to be allocated, but simulations need them sooner
    2826          801 :         if (!state.dataHeatBal->ZoneIntGain.allocated()) {
    2827            0 :             DataHeatBalance::AllocateIntGains(state);
    2828              :         }
    2829          801 :         state.dataZoneTempPredictorCorrector->zoneHeatBalance.allocate(state.dataGlobal->NumOfZones);
    2830              :         // Always allocate spaceHeatBalance, even if doSpaceHeatBalance is false, because it's used to gather some of the zone totals
    2831          801 :         state.dataZoneTempPredictorCorrector->spaceHeatBalance.allocate(state.dataGlobal->numSpaces);
    2832              : 
    2833          801 :         state.dataHeatBal->EnclSolQSDifSol.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2834          801 :         state.dataHeatBal->EnclSolQD.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2835          801 :         state.dataHeatBal->EnclSolQDforDaylight.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2836          801 :         state.dataHeatBal->EnclSolDB.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2837          801 :         state.dataHeatBal->EnclSolDBSSG.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2838          801 :         state.dataHeatBal->EnclSolDBIntWin.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2839          801 :         state.dataHeatBal->EnclSolQSWRad.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2840          801 :         state.dataHeatBal->EnclSolQSWRadLights.allocate(state.dataViewFactor->NumOfSolarEnclosures);
    2841         6001 :         for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    2842         5200 :             state.dataHeatBal->EnclSolQSDifSol(enclosureNum) = 0.0;
    2843         5200 :             state.dataHeatBal->EnclSolQD(enclosureNum) = 0.0;
    2844         5200 :             state.dataHeatBal->EnclSolQDforDaylight(enclosureNum) = 0.0;
    2845         5200 :             state.dataHeatBal->EnclSolQSWRad(enclosureNum) = 0.0;
    2846         5200 :             state.dataHeatBal->EnclSolQSWRadLights(enclosureNum) = 0.0;
    2847         5200 :             state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    2848         5200 :             state.dataHeatBal->EnclSolDBSSG(enclosureNum) = 0.0;
    2849         5200 :             state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
    2850              :         }
    2851          801 :     }
    2852          801 :     void AllocateHeatBalArrays(EnergyPlusData &state)
    2853              :     {
    2854              : 
    2855              :         // SUBROUTINE INFORMATION:
    2856              :         //       AUTHOR         Richard Liesen
    2857              :         //       DATE WRITTEN   February 1998
    2858              : 
    2859              :         // Use the total number of zones or surfaces to allocate variables to avoid a limit
    2860          801 :         AllocateZoneHeatBalArrays(state);
    2861          801 :         state.dataHeatBalFanSys->SumConvHTRadSys.dimension(state.dataGlobal->NumOfZones, 0.0);
    2862          801 :         state.dataHeatBalFanSys->SumLatentHTRadSys.dimension(state.dataGlobal->NumOfZones, 0.0);
    2863          801 :         state.dataHeatBalFanSys->SumConvPool.dimension(state.dataGlobal->NumOfZones, 0.0);
    2864          801 :         state.dataHeatBalFanSys->SumLatentPool.dimension(state.dataGlobal->NumOfZones, 0.0);
    2865          801 :         state.dataHeatBalFanSys->ZoneQdotRadHVACToPerson.dimension(state.dataGlobal->NumOfZones, 0.0);
    2866          801 :         state.dataHeatBalFanSys->ZoneQHTRadSysToPerson.dimension(state.dataGlobal->NumOfZones, 0.0);
    2867          801 :         state.dataHeatBalFanSys->ZoneQHWBaseboardToPerson.dimension(state.dataGlobal->NumOfZones, 0.0);
    2868          801 :         state.dataHeatBalFanSys->ZoneQSteamBaseboardToPerson.dimension(state.dataGlobal->NumOfZones, 0.0);
    2869          801 :         state.dataHeatBalFanSys->ZoneQElecBaseboardToPerson.dimension(state.dataGlobal->NumOfZones, 0.0);
    2870          801 :         state.dataHeatBalFanSys->ZoneQCoolingPanelToPerson.dimension(state.dataGlobal->NumOfZones, 0.0);
    2871          801 :         state.dataHeatBalFanSys->ZoneReOrder.allocate(state.dataGlobal->NumOfZones);
    2872          801 :         state.dataHeatBalFanSys->ZoneMassBalanceFlag.dimension(state.dataGlobal->NumOfZones, false);
    2873          801 :         state.dataHeatBalFanSys->ZoneInfiltrationFlag.dimension(state.dataGlobal->NumOfZones, false);
    2874          801 :         state.dataHeatBalFanSys->ZoneReOrder = 0;
    2875          801 :         state.dataHeatBalFanSys->TempTstatAir.dimension(state.dataGlobal->NumOfZones, DataHeatBalance::ZoneInitialTemp);
    2876          801 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2877           15 :             state.dataContaminantBalance->OutdoorCO2 = state.dataContaminantBalance->Contaminant.CO2OutdoorSched->getCurrentVal();
    2878           15 :             state.dataContaminantBalance->ZoneAirCO2.dimension(state.dataGlobal->NumOfZones, state.dataContaminantBalance->OutdoorCO2);
    2879           15 :             state.dataContaminantBalance->ZoneAirCO2Temp.dimension(state.dataGlobal->NumOfZones, state.dataContaminantBalance->OutdoorCO2);
    2880           15 :             state.dataContaminantBalance->ZoneAirCO2Avg.dimension(state.dataGlobal->NumOfZones, state.dataContaminantBalance->OutdoorCO2);
    2881              :         }
    2882          801 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2883            3 :             state.dataContaminantBalance->OutdoorGC = state.dataContaminantBalance->Contaminant.genericOutdoorSched->getCurrentVal();
    2884            3 :             state.dataContaminantBalance->ZoneAirGC.dimension(state.dataGlobal->NumOfZones, state.dataContaminantBalance->OutdoorGC);
    2885            3 :             state.dataContaminantBalance->ZoneAirGCTemp.dimension(state.dataGlobal->NumOfZones, state.dataContaminantBalance->OutdoorGC);
    2886            3 :             state.dataContaminantBalance->ZoneAirGCAvg.dimension(state.dataGlobal->NumOfZones, state.dataContaminantBalance->OutdoorGC);
    2887              :         }
    2888          801 :         state.dataHeatBalMgr->MaxTempPrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2889          801 :         state.dataHeatBalMgr->MinTempPrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2890          801 :         state.dataHeatBalMgr->MaxHeatLoadPrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2891          801 :         state.dataHeatBalMgr->MaxCoolLoadPrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2892          801 :         state.dataHeatBalMgr->MaxHeatLoadZone.dimension(state.dataGlobal->NumOfZones, -9999.0);
    2893          801 :         state.dataHeatBalMgr->MaxCoolLoadZone.dimension(state.dataGlobal->NumOfZones, -9999.0);
    2894          801 :         state.dataHeatBalMgr->MaxTempZone.dimension(state.dataGlobal->NumOfZones, -9999.0);
    2895          801 :         state.dataHeatBalMgr->MinTempZone.dimension(state.dataGlobal->NumOfZones, 1000.0);
    2896          801 :         state.dataHeatBalMgr->TempZonePrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2897          801 :         state.dataHeatBalMgr->LoadZonePrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2898          801 :         state.dataHeatBalMgr->TempZoneSecPrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2899          801 :         state.dataHeatBalMgr->LoadZoneSecPrevDay.dimension(state.dataGlobal->NumOfZones, 0.0);
    2900          801 :         state.dataHeatBalMgr->WarmupTempDiff.dimension(state.dataGlobal->NumOfZones, 0.0);
    2901          801 :         state.dataHeatBalMgr->WarmupLoadDiff.dimension(state.dataGlobal->NumOfZones, 0.0);
    2902          801 :         state.dataHeatBalMgr->TempZone.dimension(state.dataGlobal->NumOfZones, 0.0);
    2903          801 :         state.dataHeatBalMgr->LoadZone.dimension(state.dataGlobal->NumOfZones, 0.0);
    2904          801 :         state.dataHeatBalMgr->TempZoneRpt.dimension(state.dataGlobal->NumOfZones, state.dataGlobal->TimeStepsInHour * Constant::iHoursInDay, 0.0);
    2905          801 :         state.dataHeatBalMgr->LoadZoneRpt.dimension(state.dataGlobal->NumOfZones, state.dataGlobal->TimeStepsInHour * Constant::iHoursInDay, 0.0);
    2906          801 :         state.dataHeatBalMgr->MaxLoadZoneRpt.dimension(state.dataGlobal->NumOfZones, state.dataGlobal->TimeStepsInHour * Constant::iHoursInDay, 0.0);
    2907          801 :         state.dataHeatBalMgr->WarmupConvergenceValues.allocate(state.dataGlobal->NumOfZones);
    2908          801 :         state.dataHeatBalMgr->TempZoneRptStdDev.allocate(state.dataGlobal->TimeStepsInHour * Constant::iHoursInDay);
    2909          801 :         state.dataHeatBalMgr->LoadZoneRptStdDev.allocate(state.dataGlobal->TimeStepsInHour * Constant::iHoursInDay);
    2910              :         // MassConservation.allocate( NumOfZones );
    2911              : 
    2912          801 :         state.dataHeatBalFanSys->CrossedColdThreshRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2913          801 :         state.dataHeatBalFanSys->CrossedHeatThreshRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2914          801 :         state.dataHeatBalFanSys->CrossedColdThreshRepPeriod = false;
    2915          801 :         state.dataHeatBalFanSys->CrossedHeatThreshRepPeriod = false;
    2916          801 :         if (state.dataWeather->TotThermalReportPers > 0) {
    2917            4 :             state.dataHeatBalFanSys->ZoneHeatIndexHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2918            8 :             state.dataHeatBalFanSys->ZoneHeatIndexOccupiedHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2919            4 :                                                                                      state.dataWeather->TotThermalReportPers);
    2920            8 :             state.dataHeatBalFanSys->ZoneHeatIndexOccuHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2921            4 :                                                                                  state.dataWeather->TotThermalReportPers);
    2922            4 :             state.dataHeatBalFanSys->ZoneHumidexHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2923            8 :             state.dataHeatBalFanSys->ZoneHumidexOccupiedHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2924            4 :                                                                                    state.dataWeather->TotThermalReportPers);
    2925            4 :             state.dataHeatBalFanSys->ZoneHumidexOccuHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2926            8 :             state.dataHeatBalFanSys->ZoneColdHourOfSafetyBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2927            4 :                                                                                 state.dataWeather->TotThermalReportPers);
    2928            8 :             state.dataHeatBalFanSys->ZoneHeatHourOfSafetyBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2929            4 :                                                                                 state.dataWeather->TotThermalReportPers);
    2930            4 :             state.dataHeatBalFanSys->ZoneUnmetDegreeHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2931            8 :             state.dataHeatBalFanSys->ZoneDiscomfortWtExceedOccuHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2932            4 :                                                                                           state.dataWeather->TotThermalReportPers);
    2933            8 :             state.dataHeatBalFanSys->ZoneDiscomfortWtExceedOccupiedHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2934            4 :                                                                                               state.dataWeather->TotThermalReportPers);
    2935              :         }
    2936              : 
    2937          801 :         if (state.dataWeather->TotCO2ReportPers > 0) {
    2938            2 :             state.dataHeatBalFanSys->ZoneCO2LevelHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotCO2ReportPers);
    2939            2 :             state.dataHeatBalFanSys->ZoneCO2LevelOccuHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotCO2ReportPers);
    2940            4 :             state.dataHeatBalFanSys->ZoneCO2LevelOccupiedHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2941            2 :                                                                                     state.dataWeather->TotCO2ReportPers);
    2942              :         }
    2943          801 :         if (state.dataWeather->TotVisualReportPers > 0) {
    2944            4 :             state.dataHeatBalFanSys->ZoneLightingLevelHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2945            2 :                                                                                  state.dataWeather->TotVisualReportPers);
    2946            4 :             state.dataHeatBalFanSys->ZoneLightingLevelOccuHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2947            2 :                                                                                      state.dataWeather->TotVisualReportPers);
    2948            4 :             state.dataHeatBalFanSys->ZoneLightingLevelOccupiedHourBinsRepPeriod.allocate(state.dataGlobal->NumOfZones,
    2949            2 :                                                                                          state.dataWeather->TotVisualReportPers);
    2950              :         }
    2951              : 
    2952          801 :         state.dataHeatBalFanSys->ZoneLowSETHoursRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2953          801 :         state.dataHeatBalFanSys->ZoneHighSETHoursRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2954          801 :         state.dataHeatBalFanSys->lowSETLongestHoursRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2955          801 :         state.dataHeatBalFanSys->highSETLongestHoursRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2956          801 :         state.dataHeatBalFanSys->lowSETLongestStartRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2957          801 :         state.dataHeatBalFanSys->highSETLongestStartRepPeriod.allocate(state.dataGlobal->NumOfZones, state.dataWeather->TotThermalReportPers);
    2958              : 
    2959          801 :         state.dataHeatBalMgr->CountWarmupDayPoints = 0;
    2960          801 :     }
    2961              : 
    2962              :     // End Initialization Section of the Module
    2963              :     //******************************************************************************
    2964              : 
    2965              :     // Beginning of Record Keeping subroutines for the HB Module
    2966              :     // *****************************************************************************
    2967              : 
    2968      2828211 :     void RecKeepHeatBalance(EnergyPlusData &state)
    2969              :     {
    2970              : 
    2971              :         // SUBROUTINE INFORMATION:
    2972              :         //       AUTHOR         Rick Strand
    2973              :         //       DATE WRITTEN   April 1997
    2974              :         //       MODIFIED       June 2011, Daeho Kang for individual zone maximums & convergence outputs
    2975              :         //                       July 2016, Rick Strand for movable insulation bug fix
    2976              : 
    2977              :         // PURPOSE OF THIS SUBROUTINE:
    2978              :         // This subroutine is the main driver for record keeping within the
    2979              :         // heat balance.
    2980              : 
    2981              :         // Record Maxs & Mins for individual zone
    2982     23362440 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2983     20534229 :             auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    2984     20534229 :             auto const &thisZoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum);
    2985     20534229 :             if (thisZoneHB.ZTAV > state.dataHeatBalMgr->MaxTempZone(ZoneNum)) {
    2986      3702330 :                 state.dataHeatBalMgr->MaxTempZone(ZoneNum) = thisZoneHB.ZTAV;
    2987              :             }
    2988     20534229 :             if (thisZoneHB.ZTAV < state.dataHeatBalMgr->MinTempZone(ZoneNum)) {
    2989      3911439 :                 state.dataHeatBalMgr->MinTempZone(ZoneNum) = thisZoneHB.ZTAV;
    2990              :             }
    2991     20534229 :             if (thisZoneSysEnergyDemand.airSysHeatRate > state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum)) {
    2992      3062583 :                 state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum) = thisZoneSysEnergyDemand.airSysHeatRate;
    2993              :             }
    2994     20534229 :             if (thisZoneSysEnergyDemand.airSysCoolRate > state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum)) {
    2995      2506861 :                 state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum) = thisZoneSysEnergyDemand.airSysCoolRate;
    2996              :             }
    2997              : 
    2998              :             // Record temperature and load for individual zone
    2999     20534229 :             state.dataHeatBalMgr->TempZoneSecPrevDay(ZoneNum) = state.dataHeatBalMgr->TempZonePrevDay(ZoneNum);
    3000     20534229 :             state.dataHeatBalMgr->LoadZoneSecPrevDay(ZoneNum) = state.dataHeatBalMgr->LoadZonePrevDay(ZoneNum);
    3001     20534229 :             state.dataHeatBalMgr->TempZonePrevDay(ZoneNum) = state.dataHeatBalMgr->TempZone(ZoneNum);
    3002     20534229 :             state.dataHeatBalMgr->LoadZonePrevDay(ZoneNum) = state.dataHeatBalMgr->LoadZone(ZoneNum);
    3003     20534229 :             state.dataHeatBalMgr->TempZone(ZoneNum) = thisZoneHB.ZTAV;
    3004     20534229 :             state.dataHeatBalMgr->LoadZone(ZoneNum) = max(thisZoneSysEnergyDemand.airSysHeatRate, std::abs(thisZoneSysEnergyDemand.airSysCoolRate));
    3005              : 
    3006              :             // Calculate differences in temperature and load for the last two warmup days
    3007     23109021 :             if (!state.dataGlobal->WarmupFlag && state.dataGlobal->DayOfSim == 1 &&
    3008      2574792 :                 (!state.dataGlobal->DoingSizing || state.dataGlobal->DoPureLoadCalc)) {
    3009      1463544 :                 state.dataHeatBalMgr->WarmupTempDiff(ZoneNum) =
    3010      1463544 :                     std::abs(state.dataHeatBalMgr->TempZoneSecPrevDay(ZoneNum) - state.dataHeatBalMgr->TempZonePrevDay(ZoneNum));
    3011      1463544 :                 state.dataHeatBalMgr->WarmupLoadDiff(ZoneNum) =
    3012      1463544 :                     std::abs(state.dataHeatBalMgr->LoadZoneSecPrevDay(ZoneNum) - state.dataHeatBalMgr->LoadZonePrevDay(ZoneNum));
    3013      1463544 :                 if (ZoneNum == 1) {
    3014       224184 :                     ++state.dataHeatBalMgr->CountWarmupDayPoints;
    3015              :                 }
    3016      1463544 :                 state.dataHeatBalMgr->TempZoneRpt(ZoneNum, state.dataHeatBalMgr->CountWarmupDayPoints) =
    3017      1463544 :                     state.dataHeatBalMgr->WarmupTempDiff(ZoneNum);
    3018      1463544 :                 state.dataHeatBalMgr->LoadZoneRpt(ZoneNum, state.dataHeatBalMgr->CountWarmupDayPoints) =
    3019      1463544 :                     state.dataHeatBalMgr->WarmupLoadDiff(ZoneNum);
    3020      1463544 :                 state.dataHeatBalMgr->MaxLoadZoneRpt(ZoneNum, state.dataHeatBalMgr->CountWarmupDayPoints) = state.dataHeatBalMgr->LoadZone(ZoneNum);
    3021              : 
    3022      1463544 :                 if (state.dataSysVars->ReportDetailedWarmupConvergence) { // only do this detailed thing when requested by user is on
    3023              :                     // Write Warmup Convergence Information to the initialization output file
    3024         1152 :                     if (state.dataHeatBalMgr->FirstWarmupWrite) {
    3025            1 :                         constexpr const char *Format_732{"! <Warmup Convergence Information>,Zone Name,Time Step,Hour of Day,Warmup Temperature "
    3026              :                                                          "Difference {{deltaC}},Warmup Load Difference {{W}}\n"};
    3027            1 :                         print(state.files.eio, Format_732);
    3028            1 :                         state.dataHeatBalMgr->FirstWarmupWrite = false;
    3029              :                     }
    3030         1152 :                     constexpr const char *Format_731{" Warmup Convergence Information, {},{},{},{:.10R},{:.10R}\n"};
    3031         3456 :                     print(state.files.eio,
    3032              :                           Format_731,
    3033         1152 :                           state.dataHeatBal->Zone(ZoneNum).Name,
    3034         1152 :                           state.dataGlobal->TimeStep,
    3035         1152 :                           state.dataGlobal->HourOfDay,
    3036         1152 :                           state.dataHeatBalMgr->WarmupTempDiff(ZoneNum),
    3037         1152 :                           state.dataHeatBalMgr->WarmupLoadDiff(ZoneNum));
    3038              :                 }
    3039              :             }
    3040              :         }
    3041              : 
    3042              :         // Update interior movable insulation flag--needed at the end of a zone time step so that the interior radiant
    3043              :         // exchange algorithm knows whether there has been a change in interior movable insulation or not.
    3044      2828211 :         if (state.dataSurface->AnyMovableInsulation) {
    3045        16197 :             for (int surfNum : state.dataSurface->intMovInsulSurfNums) {
    3046         6075 :                 auto &movInsul = state.dataSurface->intMovInsuls(surfNum);
    3047         6075 :                 movInsul.presentPrevTS = movInsul.present;
    3048        10122 :             }
    3049              :         }
    3050              : 
    3051              :         // For non-complex windows, update a report variable so this shows up in the output as something other than zero
    3052      2828211 :         UpdateWindowFaceTempsNonBSDFWin(state);
    3053      2828211 :     }
    3054              : 
    3055        16827 :     void CheckWarmupConvergence(EnergyPlusData &state)
    3056              :     {
    3057              : 
    3058              :         // SUBROUTINE INFORMATION:
    3059              :         //       AUTHOR         Rick Strand
    3060              :         //       DATE WRITTEN   April 1997
    3061              :         //       MODIFIED       June 2011, Daeho Kang for individual zone comparison
    3062              : 
    3063              :         // PURPOSE OF THIS SUBROUTINE:
    3064              :         // This subroutine checks warmup convergence values.
    3065              : 
    3066              :         // SUBROUTINE PARAMETER DEFINITIONS:
    3067        16827 :         Real64 constexpr MinLoad(100.0); // Minimum loads for convergence check
    3068              :         // To avoid big percentage difference in low load situations
    3069              : 
    3070              :         // Convergence criteria for warmup days:
    3071              :         // Perform another warmup day unless both the % change in loads and
    3072              :         // absolute change in zone temp min & max are less than their criteria.
    3073              : 
    3074        16827 :         if (state.dataGlobal->NumOfZones <= 0) { // if there are no zones, immediate convergence
    3075           62 :             state.dataGlobal->WarmupFlag = false;
    3076              :         } else {
    3077        16765 :             bool ConvergenceChecksFailed = false;
    3078              : 
    3079       153702 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    3080              : 
    3081       136937 :                 state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxTempValue =
    3082       136937 :                     std::abs(state.dataHeatBalMgr->MaxTempPrevDay(ZoneNum) - state.dataHeatBalMgr->MaxTempZone(ZoneNum));
    3083       136937 :                 state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMinTempValue =
    3084       136937 :                     std::abs(state.dataHeatBalMgr->MinTempPrevDay(ZoneNum) - state.dataHeatBalMgr->MinTempZone(ZoneNum));
    3085       136937 :                 if (state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxTempValue <= state.dataHeatBal->TempConvergTol) {
    3086        99190 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(1) = 2;
    3087              :                 } else {
    3088        37747 :                     ConvergenceChecksFailed = true;
    3089        37747 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(1) = 1;
    3090              :                 }
    3091              : 
    3092       136937 :                 if (state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMinTempValue <= state.dataHeatBal->TempConvergTol) {
    3093       100255 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(2) = 2;
    3094              :                 } else {
    3095        36682 :                     ConvergenceChecksFailed = true;
    3096        36682 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(2) = 1;
    3097              :                 }
    3098              : 
    3099       136937 :                 if (state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum) > 1.0e-4) { // make sure load big enough to divide
    3100        68638 :                     state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum) = std::abs(max(state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum), MinLoad));
    3101        68638 :                     state.dataHeatBalMgr->MaxHeatLoadPrevDay(ZoneNum) = std::abs(max(state.dataHeatBalMgr->MaxHeatLoadPrevDay(ZoneNum), MinLoad));
    3102        68638 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxHeatLoadValue =
    3103        68638 :                         std::abs((state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum) - state.dataHeatBalMgr->MaxHeatLoadPrevDay(ZoneNum)) /
    3104        68638 :                                  state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum));
    3105        68638 :                     if (state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxHeatLoadValue <= state.dataHeatBal->LoadsConvergTol) {
    3106        49091 :                         state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(3) = 2;
    3107              :                     } else {
    3108        19547 :                         ConvergenceChecksFailed = true;
    3109        19547 :                         state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(3) = 1;
    3110              :                     }
    3111              :                 } else {
    3112        68299 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(3) = 2;
    3113              :                 }
    3114              : 
    3115       136937 :                 if (state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum) > 1.0e-4) {
    3116        69421 :                     state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum) = std::abs(max(state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum), MinLoad));
    3117        69421 :                     state.dataHeatBalMgr->MaxCoolLoadPrevDay(ZoneNum) = std::abs(max(state.dataHeatBalMgr->MaxCoolLoadPrevDay(ZoneNum), MinLoad));
    3118        69421 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxCoolLoadValue =
    3119        69421 :                         std::abs((state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum) - state.dataHeatBalMgr->MaxCoolLoadPrevDay(ZoneNum)) /
    3120        69421 :                                  state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum));
    3121        69421 :                     if (state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxCoolLoadValue <= state.dataHeatBal->LoadsConvergTol) {
    3122        48028 :                         state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(4) = 2;
    3123              :                     } else {
    3124        21393 :                         ConvergenceChecksFailed = true;
    3125        21393 :                         state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(4) = 1;
    3126              :                     }
    3127              :                 } else {
    3128        67516 :                     state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(4) = 2;
    3129              :                 }
    3130              : 
    3131       136937 :                 if (state.dataGlobal->DayOfSim >= state.dataHeatBal->MaxNumberOfWarmupDays && state.dataGlobal->WarmupFlag) {
    3132              :                     // Check convergence for individual zone
    3133          153 :                     if (sum(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag) != 8) { // pass=2 * 4 values for convergence
    3134           42 :                         ShowSevereError(state,
    3135           42 :                                         format("CheckWarmupConvergence: Loads Initialization, Zone=\"{}\" did not converge after {} warmup days.",
    3136           21 :                                                state.dataHeatBal->Zone(ZoneNum).Name,
    3137           21 :                                                state.dataHeatBal->MaxNumberOfWarmupDays));
    3138           21 :                         if (!state.dataHeatBalMgr->WarmupConvergenceWarning && !state.dataGlobal->DoingSizing) {
    3139            8 :                             ShowContinueError(state, "See Warmup Convergence Information in .eio file for details.");
    3140            4 :                             state.dataHeatBalMgr->WarmupConvergenceWarning = true;
    3141           17 :                         } else if (!state.dataHeatBalMgr->SizingWarmupConvergenceWarning && state.dataGlobal->DoingSizing) {
    3142            0 :                             ShowContinueError(state, "Warmup Convergence failing during sizing.");
    3143            0 :                             state.dataHeatBalMgr->SizingWarmupConvergenceWarning = true;
    3144              :                         }
    3145           21 :                         if (state.dataEnvrn->RunPeriodEnvironment) {
    3146            0 :                             ShowContinueError(state, format("...Environment(RunPeriod)=\"{}\"", state.dataEnvrn->EnvironmentName));
    3147              :                         } else {
    3148           21 :                             ShowContinueError(state, format("...Environment(SizingPeriod)=\"{}\"", state.dataEnvrn->EnvironmentName));
    3149              :                         }
    3150              : 
    3151           42 :                         ShowContinueError(state,
    3152           42 :                                           format("..Max Temp Comparison = {:.2R} vs Temperature Convergence Tolerance={:.2R} - {} Convergence",
    3153           21 :                                                  state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxTempValue,
    3154           21 :                                                  state.dataHeatBal->TempConvergTol,
    3155           21 :                                                  PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(1))));
    3156           42 :                         ShowContinueError(state,
    3157           42 :                                           format("..Min Temp Comparison = {:.2R} vs Temperature Convergence Tolerance={:.2R} - {} Convergence",
    3158           21 :                                                  state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMinTempValue,
    3159           21 :                                                  state.dataHeatBal->TempConvergTol,
    3160           21 :                                                  PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(2))));
    3161           42 :                         ShowContinueError(state,
    3162           42 :                                           format("..Max Heat Load Comparison = {:.4R} vs Loads Convergence Tolerance={:.2R} - {} Convergence",
    3163           21 :                                                  state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxHeatLoadValue,
    3164           21 :                                                  state.dataHeatBal->LoadsConvergTol,
    3165           21 :                                                  PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(3))));
    3166           42 :                         ShowContinueError(state,
    3167           42 :                                           format("..Max Cool Load Comparison = {:.4R} vs Loads Convergence Tolerance={:.2R} - {} Convergence",
    3168           21 :                                                  state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).TestMaxCoolLoadValue,
    3169           21 :                                                  state.dataHeatBal->LoadsConvergTol,
    3170           21 :                                                  PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(4))));
    3171              :                     }
    3172              :                 }
    3173              : 
    3174              :                 // Transfer current daily max and min loads and temperatures to the
    3175              :                 // variables containing the last day's values
    3176       136937 :                 state.dataHeatBalMgr->MaxHeatLoadPrevDay(ZoneNum) = state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum);
    3177       136937 :                 state.dataHeatBalMgr->MaxCoolLoadPrevDay(ZoneNum) = state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum);
    3178       136937 :                 state.dataHeatBalMgr->MaxTempPrevDay(ZoneNum) = state.dataHeatBalMgr->MaxTempZone(ZoneNum);
    3179       136937 :                 state.dataHeatBalMgr->MinTempPrevDay(ZoneNum) = state.dataHeatBalMgr->MinTempZone(ZoneNum);
    3180              : 
    3181       136937 :                 state.dataHeatBalMgr->MaxHeatLoadZone(ZoneNum) = -9999.0;
    3182       136937 :                 state.dataHeatBalMgr->MaxCoolLoadZone(ZoneNum) = -9999.0;
    3183       136937 :                 state.dataHeatBalMgr->MaxTempZone(ZoneNum) = -9999.0;
    3184       136937 :                 state.dataHeatBalMgr->MinTempZone(ZoneNum) = 1000.0;
    3185              :             }
    3186              : 
    3187              :             // Limit the number of warmup days, regardless of the number of zones
    3188              :             // in the building, to some arbitrary value based on common sense and
    3189              :             // experience with the (I)BLAST program.  If too many warmup days were
    3190              :             // required, notify the program user.
    3191              : 
    3192        16765 :             if ((state.dataGlobal->DayOfSim >= state.dataHeatBal->MaxNumberOfWarmupDays) && state.dataGlobal->WarmupFlag && ConvergenceChecksFailed) {
    3193            5 :                 if (state.dataHeatBal->MaxNumberOfWarmupDays < DataHeatBalance::DefaultMaxNumberOfWarmupDays) {
    3194            4 :                     ShowSevereError(state,
    3195            4 :                                     format("CheckWarmupConvergence: User supplied maximum warmup days={} is insufficient.",
    3196            2 :                                            state.dataHeatBal->MaxNumberOfWarmupDays));
    3197            4 :                     ShowContinueError(
    3198              :                         state,
    3199            4 :                         format("Suggest setting maximum number of warmup days to at least {}.", DataHeatBalance::DefaultMaxNumberOfWarmupDays));
    3200              :                 }
    3201              :             }
    3202              : 
    3203              :             // Set warmup flag to true depending on value of ConvergenceChecksFailed (true=fail)
    3204              :             // and minimum number of warmup days
    3205        16765 :             if (!ConvergenceChecksFailed && state.dataGlobal->DayOfSim >= state.dataHeatBal->MinNumberOfWarmupDays) {
    3206         2579 :                 state.dataGlobal->WarmupFlag = false;
    3207        14186 :             } else if (!ConvergenceChecksFailed && state.dataGlobal->DayOfSim < state.dataHeatBal->MinNumberOfWarmupDays) {
    3208         5669 :                 state.dataGlobal->WarmupFlag = true;
    3209              :             }
    3210              : 
    3211              :             // If max warmup days reached and still WarmupFlag, then go to non-warmup state.
    3212              :             // prior messages will have been displayed
    3213        16765 :             if ((state.dataGlobal->DayOfSim >= state.dataHeatBal->MaxNumberOfWarmupDays) && state.dataGlobal->WarmupFlag) {
    3214            5 :                 state.dataGlobal->WarmupFlag = false;
    3215              :             }
    3216              :         }
    3217        16827 :     }
    3218              : 
    3219         1706 :     void ReportWarmupConvergence(EnergyPlusData &state)
    3220              :     {
    3221              : 
    3222              :         // SUBROUTINE INFORMATION:
    3223              :         //       AUTHOR         Linda Lawrie
    3224              :         //       DATE WRITTEN   October 2011
    3225              : 
    3226              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3227              :         Real64 AverageZoneTemp;
    3228              :         Real64 AverageZoneLoad;
    3229              :         Real64 StdDevZoneTemp;
    3230              :         Real64 StdDevZoneLoad;
    3231              : 
    3232         1706 :         if (!state.dataGlobal->WarmupFlag) { // Report out average/std dev
    3233              :             // Write Warmup Convervence Information to the initialization output file
    3234         1706 :             if (state.dataHeatBalMgr->ReportWarmupConvergenceFirstWarmupWrite && state.dataGlobal->NumOfZones > 0) {
    3235          767 :                 constexpr const char *Format_730(
    3236              :                     "! <Warmup Convergence Information>,Zone Name,Environment Type/Name,Average Warmup Temperature Difference "
    3237              :                     "{{deltaC}},Std Dev Warmup Temperature Difference {{deltaC}},Max Temperature Pass/Fail Convergence,Min "
    3238              :                     "Temperature Pass/Fail Convergence,Average Warmup Load Difference {{W}},Std Dev Warmup Load Difference "
    3239              :                     "{{W}},Heating Load Pass/Fail Convergence,Cooling Load Pass/Fail Convergence\n");
    3240          767 :                 print(state.files.eio, Format_730);
    3241          767 :                 state.dataHeatBalMgr->ReportWarmupConvergenceFirstWarmupWrite = false;
    3242              :             }
    3243              : 
    3244         1706 :             state.dataHeatBalMgr->TempZoneRptStdDev = 0.0;
    3245         1706 :             state.dataHeatBalMgr->LoadZoneRptStdDev = 0.0;
    3246              : 
    3247         1706 :             std::string EnvHeader;
    3248         1706 :             if (state.dataEnvrn->RunPeriodEnvironment) {
    3249            7 :                 EnvHeader = "RunPeriod:";
    3250              :             } else {
    3251         1699 :                 EnvHeader = "SizingPeriod:";
    3252              :             }
    3253              : 
    3254        13297 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    3255        23182 :                 AverageZoneTemp = sum(state.dataHeatBalMgr->TempZoneRpt(ZoneNum, {1, state.dataHeatBalMgr->CountWarmupDayPoints})) /
    3256        11591 :                                   double(state.dataHeatBalMgr->CountWarmupDayPoints);
    3257      1475135 :                 for (int Num = 1; Num <= state.dataHeatBalMgr->CountWarmupDayPoints; ++Num) {
    3258      1463544 :                     if (state.dataHeatBalMgr->MaxLoadZoneRpt(ZoneNum, Num) > 1.e-4) {
    3259      1174267 :                         state.dataHeatBalMgr->LoadZoneRpt(ZoneNum, Num) /= state.dataHeatBalMgr->MaxLoadZoneRpt(ZoneNum, Num);
    3260              :                     } else {
    3261       289277 :                         state.dataHeatBalMgr->LoadZoneRpt(ZoneNum, Num) = 0.0;
    3262              :                     }
    3263              :                 }
    3264        23182 :                 AverageZoneLoad = sum(state.dataHeatBalMgr->LoadZoneRpt(ZoneNum, {1, state.dataHeatBalMgr->CountWarmupDayPoints})) /
    3265        11591 :                                   double(state.dataHeatBalMgr->CountWarmupDayPoints);
    3266        11591 :                 StdDevZoneTemp = 0.0;
    3267        11591 :                 StdDevZoneLoad = 0.0;
    3268      1475135 :                 for (int Num = 1; Num <= state.dataHeatBalMgr->CountWarmupDayPoints; ++Num) {
    3269      1463544 :                     state.dataHeatBalMgr->TempZoneRptStdDev(Num) = pow_2(state.dataHeatBalMgr->TempZoneRpt(ZoneNum, Num) - AverageZoneTemp);
    3270      1463544 :                     state.dataHeatBalMgr->LoadZoneRptStdDev(Num) = pow_2(state.dataHeatBalMgr->LoadZoneRpt(ZoneNum, Num) - AverageZoneLoad);
    3271              :                 }
    3272        11591 :                 StdDevZoneTemp = std::sqrt(sum(state.dataHeatBalMgr->TempZoneRptStdDev({1, state.dataHeatBalMgr->CountWarmupDayPoints})) /
    3273        11591 :                                            double(state.dataHeatBalMgr->CountWarmupDayPoints));
    3274        11591 :                 StdDevZoneLoad = std::sqrt(sum(state.dataHeatBalMgr->LoadZoneRptStdDev({1, state.dataHeatBalMgr->CountWarmupDayPoints})) /
    3275        11591 :                                            double(state.dataHeatBalMgr->CountWarmupDayPoints));
    3276              : 
    3277        11591 :                 constexpr const char *Format_731(" Warmup Convergence Information,{},{},{:.10R},{:.10R},{},{},{:.10R},{:.10R},{},{}\n");
    3278        11591 :                 print(state.files.eio,
    3279              :                       Format_731,
    3280        11591 :                       state.dataHeatBal->Zone(ZoneNum).Name,
    3281        23182 :                       EnvHeader + ' ' + state.dataEnvrn->EnvironmentName,
    3282              :                       AverageZoneTemp,
    3283              :                       StdDevZoneTemp,
    3284        11591 :                       PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(1)),
    3285        11591 :                       PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(2)),
    3286              :                       AverageZoneLoad,
    3287              :                       StdDevZoneLoad,
    3288        11591 :                       PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(3)),
    3289        11591 :                       PassFail(state.dataHeatBalMgr->WarmupConvergenceValues(ZoneNum).PassFlag(4)));
    3290              :             }
    3291         1706 :         }
    3292         1706 :     }
    3293              : 
    3294      2828211 :     void UpdateWindowFaceTempsNonBSDFWin(EnergyPlusData &state)
    3295              :     {
    3296     26669538 :         for (int SurfNum : state.dataSurface->AllHTWindowSurfaceList) {
    3297     23841327 :             auto &thisConstruction = state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction);
    3298     23841327 :             if (thisConstruction.WindowTypeBSDF) {
    3299        39540 :                 continue;
    3300              :             }
    3301     23801787 :             state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfNum, 1) = state.dataHeatBalSurf->SurfOutsideTempHist(1)(SurfNum);
    3302     23801787 :             state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfNum, thisConstruction.TotLayers) = state.dataHeatBalSurf->SurfInsideTempHist(1)(SurfNum);
    3303      2828211 :         }
    3304      2828211 :     }
    3305              : 
    3306              :     //        End of Record Keeping subroutines for the HB Module
    3307              :     // *****************************************************************************
    3308              : 
    3309              :     // Beginning of Reporting subroutines for the HB Module
    3310              :     // *****************************************************************************
    3311              : 
    3312      2828211 :     void ReportHeatBalance(EnergyPlusData &state)
    3313              :     {
    3314              : 
    3315              :         // SUBROUTINE INFORMATION:
    3316              :         //       AUTHOR         Rick Strand
    3317              :         //       DATE WRITTEN   July 1997
    3318              : 
    3319              :         // PURPOSE OF THIS SUBROUTINE:
    3320              :         // This subroutine is the main driver for reporting within the heat
    3321              :         // balance.
    3322              : 
    3323              :         // METHODOLOGY EMPLOYED:
    3324              :         // Uses the status flags to trigger record keeping events.
    3325              : 
    3326              :         // Using/Aliasing
    3327              :         using EconomicTariff::UpdateUtilityBills; // added for computing annual utility costs
    3328              :         using NodeInputManager::CalcMoreNodeInfo;
    3329              :         using OutputReportTabular::UpdateTabularReports;
    3330              : 
    3331      2828211 :         Sched::ReportScheduleVals(state);
    3332              : 
    3333      2828211 :         if (!state.dataGlobal->WarmupFlag && state.dataGlobal->DoOutputReporting) {
    3334       491880 :             if (!state.dataGlobal->DoingSizing) {
    3335       491880 :                 CalcMoreNodeInfo(state);
    3336              :             }
    3337       491880 :             UpdateDataandReport(state, OutputProcessor::TimeStepType::Zone);
    3338       979104 :             if (state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeDesignDay ||
    3339       487224 :                 state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeRunPeriodDesign) {
    3340         4656 :                 if (state.dataHVACSizingSimMgr->hvacSizingSimulationManager) {
    3341         4656 :                     state.dataHVACSizingSimMgr->hvacSizingSimulationManager->UpdateSizingLogsZoneStep(state);
    3342              :                 }
    3343              :             }
    3344              : 
    3345       491880 :             UpdateTabularReports(state, OutputProcessor::TimeStepType::Zone);
    3346       491880 :             UpdateUtilityBills(state);
    3347      2336331 :         } else if (!state.dataGlobal->KickOffSimulation && state.dataGlobal->DoOutputReporting && state.dataSysVars->ReportDuringWarmup) {
    3348            0 :             if (state.dataGlobal->BeginDayFlag && !state.dataEnvrn->PrintEnvrnStampWarmupPrinted) {
    3349            0 :                 state.dataEnvrn->PrintEnvrnStampWarmup = true;
    3350            0 :                 state.dataEnvrn->PrintEnvrnStampWarmupPrinted = true;
    3351              :             }
    3352            0 :             if (!state.dataGlobal->BeginDayFlag) {
    3353            0 :                 state.dataEnvrn->PrintEnvrnStampWarmupPrinted = false;
    3354              :             }
    3355            0 :             if (state.dataEnvrn->PrintEnvrnStampWarmup) {
    3356            0 :                 if (state.dataReportFlag->PrintEndDataDictionary && state.dataGlobal->DoOutputReporting) {
    3357            0 :                     constexpr const char *EndOfHeaderString("End of Data Dictionary"); // End of data dictionary marker
    3358            0 :                     print(state.files.eso, "{}\n", EndOfHeaderString);
    3359            0 :                     print(state.files.mtr, "{}\n", EndOfHeaderString);
    3360            0 :                     state.dataReportFlag->PrintEndDataDictionary = false;
    3361              :                 }
    3362            0 :                 if (state.dataGlobal->DoOutputReporting) {
    3363            0 :                     constexpr const char *EnvironmentStampFormatStr("{},{},{:7.2F},{:7.2F},{:7.2F},{:7.2F}\n"); // Format descriptor for environ stamp
    3364            0 :                     print(state.files.eso,
    3365              :                           EnvironmentStampFormatStr,
    3366              :                           "1",
    3367            0 :                           "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
    3368            0 :                           state.dataEnvrn->Latitude,
    3369            0 :                           state.dataEnvrn->Longitude,
    3370            0 :                           state.dataEnvrn->TimeZoneNumber,
    3371            0 :                           state.dataEnvrn->Elevation);
    3372              : 
    3373            0 :                     print(state.files.mtr,
    3374              :                           EnvironmentStampFormatStr,
    3375              :                           "1",
    3376            0 :                           "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
    3377            0 :                           state.dataEnvrn->Latitude,
    3378            0 :                           state.dataEnvrn->Longitude,
    3379            0 :                           state.dataEnvrn->TimeZoneNumber,
    3380            0 :                           state.dataEnvrn->Elevation);
    3381            0 :                     state.dataEnvrn->PrintEnvrnStampWarmup = false;
    3382              :                 }
    3383              :             }
    3384            0 :             if (!state.dataGlobal->DoingSizing) {
    3385            0 :                 CalcMoreNodeInfo(state);
    3386              :             }
    3387            0 :             UpdateDataandReport(state, OutputProcessor::TimeStepType::Zone);
    3388            0 :             if (state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeDesignDay ||
    3389            0 :                 state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeRunPeriodDesign) {
    3390            0 :                 if (state.dataHVACSizingSimMgr->hvacSizingSimulationManager) {
    3391            0 :                     state.dataHVACSizingSimMgr->hvacSizingSimulationManager->UpdateSizingLogsZoneStep(state);
    3392              :                 }
    3393              :             }
    3394              : 
    3395      2336331 :         } else if (state.dataSysVars->UpdateDataDuringWarmupExternalInterface) { // added for FMI
    3396         3456 :             UpdateDataandReport(state, OutputProcessor::TimeStepType::Zone);
    3397         6912 :             if (state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeDesignDay ||
    3398         3456 :                 state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeRunPeriodDesign) {
    3399            0 :                 if (state.dataHVACSizingSimMgr->hvacSizingSimulationManager) {
    3400            0 :                     state.dataHVACSizingSimMgr->hvacSizingSimulationManager->UpdateSizingLogsZoneStep(state);
    3401              :                 }
    3402              :             }
    3403              :         }
    3404              :         // There is no hourly reporting in the heat balance.
    3405              : 
    3406              :         // There is no daily reporting in the heat balance.
    3407              : 
    3408              :         // There is no simulation level record keeping in the heat balance.
    3409      2828211 :     }
    3410              : 
    3411              :     //        End of Reporting subroutines for the HB Module
    3412              : 
    3413            0 :     void OpenShadingFile(EnergyPlusData &state)
    3414              :     {
    3415              : 
    3416              :         // SUBROUTINE INFORMATION:
    3417              :         //       AUTHOR         X Luo
    3418              :         //       DATE WRITTEN   August 2017
    3419              : 
    3420              :         // PURPOSE OF THIS SUBROUTINE:
    3421              :         // Open and set up headers for a external shading fraction export file.
    3422              : 
    3423            0 :         state.files.shade.ensure_open(state, "OpenOutputFiles", state.files.outputControl.extshd);
    3424            0 :         print(state.files.shade, "Surface Name,");
    3425            0 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    3426            0 :             print(state.files.shade, "{},", state.dataSurface->Surface(SurfNum).Name);
    3427              :         }
    3428            0 :         print(state.files.shade, "\n");
    3429            0 :     }
    3430          801 :     void GetFrameAndDividerData(EnergyPlusData &state) // set to true if errors found in input
    3431              :     {
    3432              : 
    3433              :         // SUBROUTINE INFORMATION:
    3434              :         //       AUTHOR         Fred Winkelmann
    3435              :         //       DATE WRITTEN   May 2000
    3436              :         //       MODIFIED       April 2002 (FCW): get window reveal data
    3437              : 
    3438              :         // PURPOSE OF THIS SUBROUTINE:
    3439              :         // Gets input data for window frame and/or divider and/or window
    3440              :         // inside/outside reveal.
    3441              : 
    3442              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3443              :         int IOStat;                            // IO Status when calling get input subroutine
    3444          801 :         Array1D_string FrameDividerAlphas(3);  // Frame/Divider Alpha names
    3445              :         int FrameDividerNum;                   // Counter to keep track of the frame/divider number
    3446              :         int FrameDividerNumAlpha;              // Number of frame/divider alpha names being passed
    3447              :         int FrameDividerNumProp;               // Number of frame/divider properties being passed
    3448          801 :         Array1D<Real64> FrameDividerProps(23); // Temporary array to transfer frame/divider properties
    3449              :         int Loop;
    3450              : 
    3451          801 :         constexpr std::array<std::string_view, static_cast<int>(DataSurfaces::NfrcProductOptions::Num)> NfrcProductNamesUC = {
    3452              :             "CASEMENTDOUBLE", "CASEMENTSINGLE",   "DUALACTION",
    3453              :             "FIXED",          "GARAGE",           "GREENHOUSE",
    3454              :             "HINGEDESCAPE",   "HORIZONTALSLIDER", "JAL",
    3455              :             "PIVOTED",        "PROJECTINGSINGLE", "PROJECTINGDUAL",
    3456              :             "DOORSIDELITE",   "SKYLIGHT",         "SLIDINGPATIODOOR",
    3457              :             "CURTAINWALL",    "SPANDRELPANEL",    "SIDEHINGEDDOOR",
    3458              :             "DOORTRANSOM",    "TROPICALAWNING",   "TUBULARDAYLIGHTINGDEVICE",
    3459              :             "VERTICALSLIDER"};
    3460              : 
    3461          801 :         constexpr std::array<std::string_view, static_cast<int>(DataSurfaces::FrameDividerType::Num)> FrameDividerTypeNamesUC = {
    3462              :             "DIVIDEDLITE", // 0
    3463              :             "SUSPENDED"    // 1
    3464              :         };
    3465              : 
    3466          801 :         state.dataHeatBalMgr->CurrentModuleObject = "WindowProperty:FrameAndDivider";
    3467         1602 :         state.dataHeatBal->TotFrameDivider =
    3468          801 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
    3469          801 :         state.dataSurface->FrameDivider.allocate(state.dataHeatBal->TotFrameDivider);
    3470          801 :         if (state.dataHeatBal->TotFrameDivider == 0) {
    3471          771 :             return;
    3472              :         }
    3473              : 
    3474           30 :         FrameDividerNum = 0;
    3475              : 
    3476           67 :         for (Loop = 1; Loop <= state.dataHeatBal->TotFrameDivider; ++Loop) {
    3477              : 
    3478              :             // Call Input Get routine to retrieve frame/divider data
    3479          111 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3480           37 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    3481              :                                                                      Loop,
    3482              :                                                                      FrameDividerAlphas,
    3483              :                                                                      FrameDividerNumAlpha,
    3484              :                                                                      FrameDividerProps,
    3485              :                                                                      FrameDividerNumProp,
    3486              :                                                                      IOStat,
    3487           37 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    3488           37 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    3489           37 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    3490           37 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    3491              : 
    3492              :             // Load the frame/divider derived type from the input data.
    3493           37 :             ++FrameDividerNum;
    3494           37 :             auto &frameDivider = state.dataSurface->FrameDivider(FrameDividerNum);
    3495           37 :             frameDivider.Name = FrameDividerAlphas(1);
    3496           37 :             frameDivider.FrameWidth = FrameDividerProps(1);
    3497           37 :             frameDivider.FrameProjectionOut = FrameDividerProps(2);
    3498           37 :             frameDivider.FrameProjectionIn = FrameDividerProps(3);
    3499           37 :             if (frameDivider.FrameWidth == 0.0) {
    3500            6 :                 frameDivider.FrameProjectionOut = 0.0;
    3501            6 :                 frameDivider.FrameProjectionIn = 0.0;
    3502              :             }
    3503           37 :             frameDivider.FrameConductance = FrameDividerProps(4);
    3504           37 :             frameDivider.FrEdgeToCenterGlCondRatio = FrameDividerProps(5);
    3505           37 :             frameDivider.FrameSolAbsorp = FrameDividerProps(6);
    3506           37 :             frameDivider.FrameVisAbsorp = FrameDividerProps(7);
    3507           37 :             frameDivider.FrameEmis = FrameDividerProps(8);
    3508              : 
    3509              :             DataSurfaces::FrameDividerType currentDividerType =
    3510           37 :                 DataSurfaces::FrameDividerType(getEnumValue(FrameDividerTypeNamesUC, FrameDividerAlphas(2)));
    3511           37 :             if (currentDividerType == DataSurfaces::FrameDividerType::Invalid) {
    3512            0 :                 ShowWarningError(state,
    3513            0 :                                  fmt::format("{}={}, Invalid {}",
    3514            0 :                                              state.dataHeatBalMgr->CurrentModuleObject,
    3515            0 :                                              std::quoted(FrameDividerAlphas(1)),
    3516            0 :                                              state.dataIPShortCut->cAlphaFieldNames(2)));
    3517            0 :                 ShowContinueError(
    3518              :                     state,
    3519            0 :                     fmt::format("Entered={}, must be DividedLite or Suspended.  Will be set to DividedLite.", std::quoted(FrameDividerAlphas(2))));
    3520            0 :                 frameDivider.DividerType = DataSurfaces::FrameDividerType::DividedLite;
    3521              :             } else {
    3522           37 :                 frameDivider.DividerType = currentDividerType;
    3523              :             }
    3524              : 
    3525           37 :             frameDivider.DividerWidth = FrameDividerProps(9);
    3526           37 :             frameDivider.HorDividers = FrameDividerProps(10);
    3527           37 :             frameDivider.VertDividers = FrameDividerProps(11);
    3528           37 :             frameDivider.DividerProjectionOut = FrameDividerProps(12);
    3529           37 :             frameDivider.DividerProjectionIn = FrameDividerProps(13);
    3530           37 :             if (frameDivider.DividerWidth == 0.0 || frameDivider.DividerType == DataSurfaces::FrameDividerType::Suspended) {
    3531           17 :                 frameDivider.DividerProjectionOut = 0.0;
    3532           17 :                 frameDivider.DividerProjectionIn = 0.0;
    3533              :             }
    3534           37 :             frameDivider.DividerConductance = FrameDividerProps(14);
    3535           37 :             frameDivider.DivEdgeToCenterGlCondRatio = FrameDividerProps(15);
    3536           37 :             frameDivider.DividerSolAbsorp = FrameDividerProps(16);
    3537           37 :             frameDivider.DividerVisAbsorp = FrameDividerProps(17);
    3538           37 :             frameDivider.DividerEmis = FrameDividerProps(18);
    3539              : 
    3540              :             // look up the NFRC Product Type for Assembly Calculations using the DataSurfaces::NfrcProductName
    3541           37 :             frameDivider.NfrcProductType = DataSurfaces::NfrcProductOptions(getEnumValue(NfrcProductNamesUC, FrameDividerAlphas(3)));
    3542           37 :             if (frameDivider.NfrcProductType == DataSurfaces::NfrcProductOptions::Invalid) {
    3543            0 :                 frameDivider.NfrcProductType = DataSurfaces::NfrcProductOptions::CurtainWall;
    3544              :             }
    3545              : 
    3546           37 :             frameDivider.OutsideRevealSolAbs = FrameDividerProps(19);
    3547           37 :             frameDivider.InsideSillDepth = FrameDividerProps(20);
    3548           37 :             frameDivider.InsideSillSolAbs = FrameDividerProps(21);
    3549           37 :             frameDivider.InsideReveal = FrameDividerProps(22);
    3550           37 :             frameDivider.InsideRevealSolAbs = FrameDividerProps(23);
    3551              : 
    3552           37 :             if (frameDivider.DividerWidth > 0.0 && (frameDivider.HorDividers == 0 && frameDivider.VertDividers == 0)) {
    3553            0 :                 ShowWarningError(state,
    3554            0 :                                  format("{}: In FrameAndDivider {} {} > 0 ",
    3555            0 :                                         state.dataHeatBalMgr->CurrentModuleObject,
    3556            0 :                                         frameDivider.Name,
    3557            0 :                                         state.dataIPShortCut->cNumericFieldNames(9)));
    3558            0 :                 ShowContinueError(
    3559              :                     state,
    3560            0 :                     format("...but {} = 0 and {} = 0.", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->cNumericFieldNames(11)));
    3561            0 :                 ShowContinueError(state, format("...{} set to 0.", state.dataIPShortCut->cNumericFieldNames(9)));
    3562            0 :                 frameDivider.DividerWidth = 0.0;
    3563              :             }
    3564              :             // Prevent InsideSillDepth < InsideReveal
    3565           37 :             if (frameDivider.InsideSillDepth < state.dataSurface->FrameDivider(FrameDividerNum).InsideReveal) {
    3566            0 :                 ShowWarningError(state,
    3567            0 :                                  format("{}: In FrameAndDivider {} {} is less than {}; it will be set to {}.",
    3568            0 :                                         state.dataHeatBalMgr->CurrentModuleObject,
    3569            0 :                                         frameDivider.Name,
    3570            0 :                                         state.dataIPShortCut->cNumericFieldNames(20),
    3571            0 :                                         state.dataIPShortCut->cNumericFieldNames(22),
    3572            0 :                                         state.dataIPShortCut->cNumericFieldNames(22)));
    3573            0 :                 frameDivider.InsideSillDepth = state.dataSurface->FrameDivider(FrameDividerNum).InsideReveal;
    3574              :             }
    3575              : 
    3576              :             //    ! Warn if InsideSillDepth OR InsideReveal > 0.2meters to warn of inaccuracies
    3577              :             //    IF(FrameDivider(FrameDividerNum)%InsideSillDepth > 0.2d0) THEN
    3578              :             //      CALL ShowWarningError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//': In FrameAndDivider
    3579              :             //      '//TRIM(FrameDivider(FrameDividerNum)%Name)// &
    3580              :             //        ' '//TRIM(cNumericFieldNames(20))//' is greater than 0.2 meters, which could cause inaccuracies in zone cooling energy.')
    3581              :             //    END IF
    3582              :             //    IF(FrameDivider(FrameDividerNum)%InsideReveal > 0.2d0) THEN
    3583              :             //      CALL ShowWarningError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//': In FrameAndDivider
    3584              :             //      '//TRIM(FrameDivider(FrameDividerNum)%Name)// &
    3585              :             //        ' '//TRIM(cNumericFieldNames(22))//' is greater than 0.2 meters, which could cause inaccuracies in zone cooling energy.')
    3586              :             //    END IF
    3587              :         }
    3588         1572 :     }
    3589              : 
    3590            5 :     void SearchWindow5DataFile(EnergyPlusData &state,
    3591              :                                fs::path const &DesiredFilePath,            // File path that contains the Window5 constructions.
    3592              :                                std::string const &DesiredConstructionName, // Name that will be searched for in the Window5 data file
    3593              :                                bool &ConstructionFound,                    // True if DesiredConstructionName is in the Window5 data file
    3594              :                                bool &EOFonFile,                            // True if EOF during file read
    3595              :                                bool &ErrorsFound                           // True if there is a problem with the entry requested from the data file
    3596              :     )
    3597              :     {
    3598              : 
    3599              :         // SUBROUTINE INFORMATION:
    3600              :         //       AUTHOR         Fred Winkelmann
    3601              :         //       DATE WRITTEN   August 2001
    3602              :         //       MODIFIED       June 2002, FW: do all reallocation here for constructions found on
    3603              :         //                        data file; 1 new construction of entry has one glazing system;
    3604              :         //                        2 new constructions if entry has two glazing systems.
    3605              :         //                      Nov 2002, FW: skip read of mullion data line if one glazing system;
    3606              :         //                        add error messages for bad data; increase length of input line
    3607              :         //                        from 132 to 200 to handle case where Window5 puts in extra blanks
    3608              :         //                        in gas data line.
    3609              :         //                      Feb 2007, LKL: Add more checks on Window5DataFile
    3610              :         //                      Jan 2008, LKL: Change Edge/Cond ratio check.
    3611              : 
    3612              :         // PURPOSE OF THIS SUBROUTINE:
    3613              :         // Searches the WINDOW5 data file for a window with the name "DesiredConstructionName,"
    3614              :         // which is the name of an idf Construction input using CONSTRUCTION FROM WINDOW5 DATA FILE.
    3615              :         // (The WINDOW5 data file contains data for one or more complete windows --
    3616              :         // glazing, frame, mullion, and divider.
    3617              :         // WINDOW5 writes the data file for export to EnergyPlus so that an annual energy
    3618              :         // analysis can be done on exactly the same window without having to re-input into
    3619              :         // EnergyPlus.)
    3620              : 
    3621              :         // If a match is found, a Construction is created and the Material objects associated with
    3622              :         // the Construction are created. If there is an associated frame or
    3623              :         // divider in the Window5 data file for this Construction, a FrameAndDivider object will
    3624              :         // also be created.
    3625              : 
    3626              :         // If the window on the data file has two glazing systems, a second Construction (and its
    3627              :         // associated materials) corresponding to the second glazing system is created.
    3628              : 
    3629              :         // Using/Aliasing
    3630              :         using namespace DataStringGlobals;
    3631              :         using DataSystemVariables::CheckForActualFilePath;
    3632              : 
    3633              :         // SUBROUTINE PARAMETER DEFINITIONS:
    3634            5 :         Array1D_string const NumName(5, {"1", "2", "3", "4", "5"});
    3635              : 
    3636              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3637              :         int FileLineCount;            // counter for number of lines read (used in some error messages)
    3638            5 :         Array1D_string DataLine(100); // Array of data lines
    3639            5 :         std::string WindowNameInW5DataFile;
    3640            5 :         std::string W5Name;
    3641            5 :         Array1D_string GasName(3);      // Gas name from data file
    3642            5 :         std::string LayerName;          // Layer name from data file
    3643            5 :         std::string MullionOrientation; // Horizontal, vertical or none
    3644              :         int LineNum;
    3645            5 :         Array1D_int NGlass(2);              // Number of glass layers in glazing system
    3646            5 :         Array2D_int NumGases(4, 2);         // Number of gases in each gap of a glazing system
    3647            5 :         Array2D_int MaterNumSysGlass(5, 2); // Material numbers for glazing system / glass combinations
    3648            5 :         Array2D_int MaterNumSysGap(4, 2);   // Material numbers for glazing system / gap combinations
    3649              :         int TotFrameDividerPrev;            // Number of FrameAndDivider objects before adding ones from W5DataFile
    3650            5 :         Array1D_int NGaps(2);               // Number of gaps in window construction
    3651              :         int NGlSys;                         // Number of glazing systems (normally 1, but 2 for mullioned window
    3652              :         //  with two different glazing systems
    3653              :         int loop;      // DO loop counter
    3654              :         int ILine;     // Line counter
    3655              :         int ConstrNum; // Construction number
    3656              :         int IGlass;    // Glass layer counter
    3657              :         int IGap;      // Gap counter
    3658              :         //  INTEGER            :: ICoeff              ! Gas property coefficient counter
    3659              :         int IGlSys;                   // Glazing system counter
    3660              :         int FrDivNum;                 // FrameDivider number
    3661            5 :         Array1D<Real64> WinHeight(2); // Height, width for glazing system (m)
    3662            5 :         Array1D<Real64> WinWidth(2);
    3663            5 :         Array1D<Real64> UValCenter(2);                 // Center of glass U-value (W/m2-K) for glazing system
    3664            5 :         Array1D<Real64> SCCenter(2);                   // Center of glass shading coefficient for glazing system
    3665            5 :         Array1D<Real64> SHGCCenter(2);                 // Center of glass solar heat gain coefficient for glazing system
    3666            5 :         Array1D<Real64> TVisCenter(2);                 // Center of glass visible transmittance for glazing system
    3667            5 :         Array1D<Real64> TsolTemp(Window::numPhis + 1); // Solar transmittance vs incidence angle; diffuse trans.
    3668              :         std::array<Real64, Window::numPhis> Tsol;
    3669            5 :         Array2D<Real64> AbsSolTemp(Window::maxGlassLayers, Window::numPhis + 1);     // Solar absorptance vs inc. angle in each glass layer
    3670            5 :         Array1D<std::array<Real64, Window::numPhis>> AbsSol(Window::maxGlassLayers); // Solar absorptance vs inc. angle in each glass layer
    3671            5 :         Array1D<Real64> RfsolTemp(Window::numPhis + 1);                              // Front solar reflectance vs inc. angle
    3672              :         std::array<Real64, Window::numPhis> Rfsol;
    3673            5 :         Array1D<Real64> RbsolTemp(Window::numPhis + 1); // Back solar reflectance vs inc. angle
    3674              :         std::array<Real64, Window::numPhis> Rbsol;
    3675            5 :         Array1D<Real64> TvisTemp(Window::numPhis + 1); // Visible transmittance vs inc. angle
    3676              :         std::array<Real64, Window::numPhis> Tvis;
    3677            5 :         Array1D<Real64> RfvisTemp(Window::numPhis + 1); // Front visible reflectance vs inc. angle
    3678              :         std::array<Real64, Window::numPhis> Rfvis;
    3679            5 :         Array1D<Real64> RbvisTemp(Window::numPhis + 1); // Back visible reflectance vs inc. angle
    3680              :         std::array<Real64, Window::numPhis> Rbvis;
    3681              : 
    3682              :         std::array<Real64, Window::numPhis> tsolFit;  // Fitted solar transmittance vs incidence angle
    3683              :         std::array<Real64, Window::numPhis> tvisFit;  // Fitted visible transmittance vs incidence angle
    3684              :         std::array<Real64, Window::numPhis> rfsolFit; // Fitted solar front reflectance vs incidence angle
    3685              :         Array1D<std::array<Real64, Window::numPhis>> solabsFit(
    3686            5 :             Window::maxGlassLayers);   // Fitted solar absorptance vs incidence angle for each glass layer
    3687            5 :         Array1D_string DividerType(2); // Divider type: DividedLite or Suspended
    3688              :         Real64 FrameWidth;
    3689              :         Real64 MullionWidth;
    3690              :         Real64 FrameProjectionOut;
    3691              :         Real64 FrameProjectionIn;
    3692              :         Real64 FrameConductance;
    3693              :         Real64 FrEdgeToCenterGlCondRatio;
    3694              :         Real64 FrameSolAbsorp;
    3695              :         Real64 FrameVisAbsorp;
    3696              :         Real64 FrameEmis;
    3697            5 :         Array1D_int HorDividers(2);  // For divider: number horizontal for each glazing system
    3698            5 :         Array1D_int VertDividers(2); // For divider: number vertical for each glazing system
    3699            5 :         Array1D<Real64> DividerWidth(2);
    3700            5 :         Array1D<Real64> DividerProjectionOut(2);
    3701            5 :         Array1D<Real64> DividerProjectionIn(2);
    3702            5 :         Array1D<Real64> DividerConductance(2);
    3703            5 :         Array1D<Real64> DivEdgeToCenterGlCondRatio(2);
    3704            5 :         Array1D<Real64> DividerSolAbsorp(2);
    3705            5 :         Array1D<Real64> DividerVisAbsorp(2);
    3706            5 :         Array1D<Real64> DividerEmis(2);
    3707              :         std::string::size_type endcol;
    3708              : 
    3709            5 :         auto &s_mat = state.dataMaterial;
    3710              :         // Object Data
    3711              : 
    3712              :         // In the following four gas-related data sets, the first
    3713              :         //  index is gas type (1=air, 2=Argon, 3=Krypton, 4=Xenon)
    3714              :         //  and the second index gives a,b,c in the expression
    3715              :         //  property value = a + bT(K) + cT(K)**2, where T is mean
    3716              :         //  gap temperature in deg K.
    3717              : 
    3718            5 :         ConstructionFound = false;
    3719              :         // ErrorsFound = .FALSE.
    3720            5 :         EOFonFile = false;
    3721            5 :         std::string contextString = "HeatBalanceManager::SearchWindow5DataFile: ";
    3722              : 
    3723            5 :         state.files.TempFullFilePath.filePath = CheckForActualFilePath(state, DesiredFilePath, contextString);
    3724              : 
    3725              :         // INQUIRE(FILE=TRIM(DesiredFileName), EXIST=exists)
    3726            5 :         if (state.files.TempFullFilePath.filePath.empty()) {
    3727            0 :             ShowFatalError(state, "Program terminates due to these conditions.");
    3728              :         }
    3729              : 
    3730           10 :         auto W5DataFile = state.files.TempFullFilePath.open(state, "SearchWindow5DataFile");
    3731            5 :         auto NextLine = W5DataFile.readLine();
    3732            5 :         endcol = len(NextLine.data);
    3733            5 :         if (endcol > 0) {
    3734            5 :             if (int(NextLine.data[endcol - 1]) == DataSystemVariables::iUnicode_end) {
    3735            0 :                 ShowSevereError(state,
    3736            0 :                                 format("SearchWindow5DataFile: For \"{}\" in {} file, appears to be a Unicode or binary file.",
    3737              :                                        DesiredConstructionName,
    3738              :                                        DesiredFilePath));
    3739            0 :                 ShowContinueError(state, "...This file cannot be read by this program. Please save as PC or Unix file and try again");
    3740            0 :                 ShowFatalError(state, "Program terminates due to previous condition.");
    3741              :             }
    3742              :         }
    3743            5 :         W5DataFile.rewind();
    3744            5 :         FileLineCount = 0;
    3745              : 
    3746            5 :         NextLine = W5DataFile.readLine();
    3747            5 :         if (NextLine.eof) {
    3748            0 :             goto Label1000;
    3749              :         }
    3750            5 :         ++FileLineCount;
    3751            5 :         if (!has_prefixi(NextLine.data, "WINDOW5")) {
    3752            0 :             ShowSevereError(state, format("HeatBalanceManager: SearchWindow5DataFile: Error in Data File={}", DesiredFilePath));
    3753            0 :             ShowFatalError(
    3754              :                 state,
    3755            0 :                 format("Error reading Window5 Data File: first word of window entry is \"{}\", should be Window5.", NextLine.data.substr(0, 7)));
    3756              :         }
    3757              : 
    3758            5 :     Label10:;
    3759           25 :         for (LineNum = 2; LineNum <= 5; ++LineNum) {
    3760           20 :             NextLine = W5DataFile.readLine();
    3761           20 :             if (NextLine.eof) {
    3762            0 :                 goto Label1000;
    3763              :             }
    3764           20 :             DataLine(LineNum) = NextLine.data;
    3765           20 :             ++FileLineCount;
    3766              :         }
    3767              : 
    3768              :         // Get window name and check for match
    3769            5 :         W5Name = std::string{DataLine(4).substr(19)};
    3770            5 :         WindowNameInW5DataFile = Util::makeUPPER(W5Name);
    3771            5 :         if (DesiredConstructionName != WindowNameInW5DataFile) {
    3772              :             // Doesn't match; read through file until next window entry is found
    3773            0 :         Label20:;
    3774            0 :             NextLine = W5DataFile.readLine();
    3775            0 :             if (NextLine.eof) {
    3776            0 :                 goto Label1000;
    3777              :             }
    3778            0 :             ++FileLineCount;
    3779            0 :             if (!has_prefixi(NextLine.data, "WINDOW5")) {
    3780            0 :                 goto Label20;
    3781              :             }
    3782              :             // Beginning of next window entry found
    3783            0 :             goto Label10;
    3784              :         } else {
    3785              :             // Match found
    3786            5 :             ConstructionFound = true;
    3787              : 
    3788              :             // Create Material:WindowGlass, Material:WindowGas, Construction
    3789              :             // and WindowFrameAndDividerObjects for this window
    3790              : 
    3791            5 :             NextLine = W5DataFile.readLine();
    3792            5 :             if (NextLine.eof) {
    3793            0 :                 goto Label1000;
    3794              :             }
    3795            5 :             ++FileLineCount;
    3796            5 :             bool error = false;
    3797            5 :             NGlSys = static_cast<int>(Util::ProcessNumber(NextLine.data.substr(19), error));
    3798            5 :             if (NGlSys <= 0 || NGlSys > 2 || error) {
    3799            0 :                 ShowFatalError(
    3800              :                     state,
    3801            0 :                     format("Construction={} from the Window5 data file cannot be used: it has {} glazing systems; only 1 or 2 are allowed.",
    3802              :                            DesiredConstructionName,
    3803              :                            NGlSys));
    3804              :             }
    3805            5 :             NextLine = W5DataFile.readLine();
    3806            5 :             if (NextLine.eof) {
    3807            0 :                 goto Label1000;
    3808              :             }
    3809            5 :             ++FileLineCount;
    3810           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    3811            5 :                 NextLine = W5DataFile.readLine();
    3812            5 :                 if (NextLine.eof) {
    3813            0 :                     goto Label1000;
    3814              :                 }
    3815            5 :                 ++FileLineCount;
    3816              : 
    3817            5 :                 const bool succeeded = readList(NextLine.data.substr(19),
    3818              :                                                 WinHeight(IGlSys),
    3819              :                                                 WinWidth(IGlSys),
    3820              :                                                 NGlass(IGlSys),
    3821              :                                                 UValCenter(IGlSys),
    3822              :                                                 SCCenter(IGlSys),
    3823              :                                                 SHGCCenter(IGlSys),
    3824              :                                                 TVisCenter(IGlSys));
    3825            5 :                 if (!succeeded) {
    3826            0 :                     ShowSevereError(
    3827              :                         state,
    3828            0 :                         format("HeatBalanceManager: SearchWindow5DataFile: Error in Read of glazing system values. For glazing system={}", IGlSys));
    3829            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount, NextLine.data.substr(0, 100)));
    3830            0 :                     ErrorsFound = true;
    3831              :                 }
    3832            5 :                 if (WinHeight(IGlSys) == 0.0 || WinWidth(IGlSys) == 0.0) {
    3833            0 :                     ShowSevereError(state,
    3834            0 :                                     format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used: it "
    3835              :                                            "has window height or width = 0 for glazing system {}",
    3836              :                                            DesiredConstructionName,
    3837              :                                            IGlSys));
    3838            0 :                     ErrorsFound = true;
    3839              :                 }
    3840            5 :                 if (NGlass(IGlSys) <= 0 || NGlass(IGlSys) > 4) {
    3841            0 :                     ShowSevereError(state,
    3842            0 :                                     format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used: it "
    3843              :                                            "has 0 or more than 4 glass layers in glazing system {}",
    3844              :                                            DesiredConstructionName,
    3845              :                                            IGlSys));
    3846            0 :                     ErrorsFound = true;
    3847              :                 }
    3848            5 :                 if (UValCenter(IGlSys) <= 0.0) {
    3849            0 :                     ShowSevereError(state,
    3850            0 :                                     format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used: it "
    3851              :                                            "has Center-of-Glass U-value <= 0 in glazing system {}",
    3852              :                                            DesiredConstructionName,
    3853              :                                            IGlSys));
    3854            0 :                     ErrorsFound = true;
    3855              :                 }
    3856            5 :                 if (SCCenter(IGlSys) <= 0.0) {
    3857            0 :                     ShowWarningError(
    3858              :                         state,
    3859            0 :                         format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file has flawed data: it "
    3860              :                                "has a Shading Coefficient <= 0 in glazing system {}",
    3861              :                                DesiredConstructionName,
    3862              :                                IGlSys));
    3863              :                 }
    3864            5 :                 if (SHGCCenter(IGlSys) <= 0.0) {
    3865            0 :                     ShowWarningError(
    3866              :                         state,
    3867            0 :                         format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file has flawed data: it "
    3868              :                                "has a SHGC <= 0 in glazing system {}",
    3869              :                                DesiredConstructionName,
    3870              :                                IGlSys));
    3871              :                 }
    3872            5 :                 WinHeight(IGlSys) *= 0.001;
    3873            5 :                 WinWidth(IGlSys) *= 0.001;
    3874              :             }
    3875           60 :             for (LineNum = 1; LineNum <= 11; ++LineNum) {
    3876           55 :                 NextLine = W5DataFile.readLine();
    3877           55 :                 if (NextLine.eof) {
    3878            0 :                     goto Label1000;
    3879              :                 }
    3880           55 :                 DataLine(LineNum) = NextLine.data;
    3881              :             }
    3882              : 
    3883              :             // Mullion width and orientation
    3884            5 :             MullionWidth = 0.0;
    3885            5 :             MullionOrientation = "Vertical";
    3886            5 :             if (NGlSys == 2) {
    3887            0 :                 error = false;
    3888            0 :                 MullionWidth = Util::ProcessNumber(DataLine(10).substr(19), error);
    3889            0 :                 if (error) {
    3890            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Mullion Width.");
    3891            0 :                     ShowContinueError(state,
    3892            0 :                                       format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 10, DataLine(10).substr(0, 100)));
    3893            0 :                     ErrorsFound = true;
    3894              :                 }
    3895            0 :                 MullionWidth *= 0.001;
    3896            0 :                 MullionOrientation = Util::ProcessNumber(DataLine(10).substr(88), error);
    3897            0 :                 if (error) {
    3898            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Mullion Orientation.");
    3899            0 :                     ShowContinueError(state,
    3900            0 :                                       format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 10, DataLine(10).substr(0, 100)));
    3901            0 :                     ErrorsFound = true;
    3902              :                 }
    3903              :             }
    3904              : 
    3905              :             // Frame data; if there are two glazing systems, the frame is assumed to be
    3906              :             // the same for both.
    3907            5 :             FrameWidth = 0.0;
    3908            5 :             FrameProjectionOut = 0.0;
    3909            5 :             FrameProjectionIn = 0.0;
    3910            5 :             FrameConductance = 0.0;
    3911            5 :             FrEdgeToCenterGlCondRatio = 0.0;
    3912            5 :             FrameSolAbsorp = 0.0;
    3913            5 :             FrameVisAbsorp = 0.0;
    3914            5 :             FrameEmis = 0.0;
    3915            5 :             const bool succeeded = readList(DataLine(11).substr(19),
    3916              :                                             FrameWidth,
    3917              :                                             FrameProjectionOut,
    3918              :                                             FrameProjectionIn,
    3919              :                                             FrameConductance,
    3920              :                                             FrEdgeToCenterGlCondRatio,
    3921              :                                             FrameSolAbsorp,
    3922              :                                             FrameVisAbsorp,
    3923              :                                             FrameEmis);
    3924            5 :             if (!succeeded) {
    3925            0 :                 ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of frame data values.");
    3926            0 :                 ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 11, DataLine(11).substr(0, 100)));
    3927            0 :                 ErrorsFound = true;
    3928              :             }
    3929            5 :             if (FrameWidth > 0.0) {
    3930            5 :                 if (FrameConductance <= 0.0) {
    3931            0 :                     ShowSevereError(state,
    3932            0 :                                     format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used: it "
    3933              :                                            "has Frame Conductance <= 0.0",
    3934              :                                            DesiredConstructionName));
    3935            0 :                     ErrorsFound = true;
    3936              :                 }
    3937              :                 // Relax this check for Window5 data: 1/28/2008.
    3938              :                 //        IF(FrEdgeToCenterGlCondRatio < 1.0) THEN
    3939              :                 //            CALL ShowSevereError(state, 'HeatBalanceManager: SearchWindow5DataFile: Construction='//TRIM(DesiredConstructionName)//
    3940              :                 //            & ' from the Window5 data file cannot be used: it has Frame Edge-of-Glass Conduction Ratio < 1.0')
    3941              :                 //          ErrorsFound = .TRUE.
    3942              :                 //        END IF
    3943            5 :                 if (FrameSolAbsorp < 0.0 || FrameSolAbsorp > 1.0) {
    3944            0 :                     ShowSevereError(state,
    3945            0 :                                     "HeatBalanceManager: SearchWindow5DataFile: Construction=" + DesiredConstructionName +
    3946              :                                         " from the Window5 data file cannot be used: it has Frame Solar Absorptance < 0.0 or > 1.0");
    3947            0 :                     ErrorsFound = true;
    3948              :                 }
    3949            5 :                 if (FrameEmis <= 0.0 || FrameEmis >= 1.0) {
    3950            0 :                     ShowSevereError(
    3951              :                         state,
    3952            0 :                         format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used: it has "
    3953              :                                "Frame Emissivity <= 0.0 or >= 1.0",
    3954              :                                DesiredConstructionName));
    3955            0 :                     ErrorsFound = true;
    3956              :                 }
    3957              :             }
    3958            5 :             FrameWidth *= 0.001;
    3959            5 :             FrameProjectionOut *= 0.001;
    3960            5 :             FrameProjectionIn *= 0.001;
    3961            5 :             FileLineCount += 11;
    3962              : 
    3963            5 :             NextLine = W5DataFile.readLine();
    3964            5 :             if (NextLine.eof) {
    3965            0 :                 goto Label1000;
    3966              :             }
    3967            5 :             ++FileLineCount;
    3968              : 
    3969              :             // Divider data for each glazing system
    3970           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    3971            5 :                 NextLine = W5DataFile.readLine();
    3972            5 :                 if (NextLine.eof) {
    3973            0 :                     goto Label1000;
    3974              :                 }
    3975            5 :                 ++FileLineCount;
    3976              : 
    3977            5 :                 const bool dividerReadSucceeded = readList(NextLine.data.substr(19),
    3978              :                                                            DividerWidth(IGlSys),
    3979              :                                                            DividerProjectionOut(IGlSys),
    3980              :                                                            DividerProjectionIn(IGlSys),
    3981              :                                                            DividerConductance(IGlSys),
    3982              :                                                            DivEdgeToCenterGlCondRatio(IGlSys),
    3983              :                                                            DividerSolAbsorp(IGlSys),
    3984              :                                                            DividerVisAbsorp(IGlSys),
    3985              :                                                            DividerEmis(IGlSys),
    3986              :                                                            DividerType(IGlSys),
    3987              :                                                            HorDividers(IGlSys),
    3988              :                                                            VertDividers(IGlSys));
    3989            5 :                 if (!dividerReadSucceeded) {
    3990            0 :                     ShowSevereError(
    3991              :                         state,
    3992            0 :                         format("HeatBalanceManager: SearchWindow5DataFile: Error in Read of divider data values. For Glazing System={}", IGlSys));
    3993            0 :                     ShowContinueError(state,
    3994            0 :                                       format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 11, NextLine.data.substr(0, 100)));
    3995            0 :                     ErrorsFound = true;
    3996              :                 }
    3997            5 :                 uppercase(DividerType(IGlSys));
    3998            5 :                 if (DividerWidth(IGlSys) > 0.0) {
    3999            5 :                     if (HorDividers(IGlSys) == 0 && VertDividers(IGlSys) == 0) {
    4000            0 :                         ShowSevereError(
    4001              :                             state,
    4002            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used:",
    4003              :                                    DesiredConstructionName));
    4004            0 :                         ShowContinueError(
    4005            0 :                             state, format("glazing system {} has a divider but number of horizontal and vertical divider elements = 0", IGlSys));
    4006            0 :                         ErrorsFound = true;
    4007              :                     }
    4008            5 :                     if (DividerConductance(IGlSys) <= 0.0) {
    4009            0 :                         ShowSevereError(
    4010              :                             state,
    4011            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used:",
    4012              :                                    DesiredConstructionName));
    4013            0 :                         ShowContinueError(state, format("glazing system {} has Divider Conductance <= 0.0", IGlSys));
    4014            0 :                         ErrorsFound = true;
    4015              :                     }
    4016            5 :                     if (DivEdgeToCenterGlCondRatio(IGlSys) < 1.0) {
    4017            0 :                         ShowSevereError(
    4018              :                             state,
    4019            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used:",
    4020              :                                    DesiredConstructionName));
    4021            0 :                         ShowContinueError(state, format("glazing system {} has Divider Edge-Of-Glass Conduction Ratio < 1.0", IGlSys));
    4022            0 :                         ErrorsFound = true;
    4023              :                     }
    4024            5 :                     if (DividerSolAbsorp(IGlSys) < 0.0 || DividerSolAbsorp(IGlSys) > 1.0) {
    4025            0 :                         ShowSevereError(
    4026              :                             state,
    4027            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used:",
    4028              :                                    DesiredConstructionName));
    4029            0 :                         ShowContinueError(state, format("glazing system {} has Divider Solar Absorptance < 0.0 or > 1.0", IGlSys));
    4030            0 :                         ErrorsFound = true;
    4031              :                     }
    4032            5 :                     if (DividerEmis(IGlSys) <= 0.0 || DividerEmis(IGlSys) >= 1.0) {
    4033            0 :                         ShowSevereError(
    4034              :                             state,
    4035            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used:",
    4036              :                                    DesiredConstructionName));
    4037            0 :                         ShowContinueError(state, format("glazing system {} has Divider Emissivity <= 0.0 or >= 1.0", IGlSys));
    4038            0 :                         ErrorsFound = true;
    4039              :                     }
    4040            5 :                     if (DividerType(IGlSys) != "DIVIDEDLITE" && DividerType(IGlSys) != "SUSPENDED") {
    4041            0 :                         ShowSevereError(
    4042              :                             state,
    4043            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used:",
    4044              :                                    DesiredConstructionName));
    4045            0 :                         ShowContinueError(
    4046              :                             state,
    4047            0 :                             format("glazing system {} has Divider Type = {}; it should be DIVIDEDLITE or SUSPENDED.", IGlSys, DividerType(IGlSys)));
    4048            0 :                         ErrorsFound = true;
    4049              :                     }
    4050              :                 }
    4051            5 :                 DividerWidth(IGlSys) *= 0.001;
    4052            5 :                 if (DividerType(IGlSys) == "DIVIDEDLITE") {
    4053            0 :                     DividerProjectionOut(IGlSys) *= 0.001;
    4054            0 :                     DividerProjectionIn(IGlSys) *= 0.001;
    4055              :                 } else {
    4056            5 :                     DividerProjectionOut(IGlSys) = 0.0;
    4057            5 :                     DividerProjectionIn(IGlSys) = 0.0;
    4058              :                 }
    4059              :             }
    4060              : 
    4061            5 :             if (ErrorsFound) {
    4062            0 :                 ShowFatalError(state,
    4063            0 :                                format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used because "
    4064              :                                       "of above errors",
    4065              :                                       DesiredConstructionName));
    4066              :             }
    4067              : 
    4068           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4069            5 :                 NGaps(IGlSys) = NGlass(IGlSys) - 1;
    4070              :             }
    4071              : 
    4072              :             // Glass objects
    4073            5 :             NextLine = W5DataFile.readLine();
    4074            5 :             if (NextLine.eof) {
    4075            0 :                 goto Label1000;
    4076              :             }
    4077            5 :             ++FileLineCount;
    4078           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4079           15 :                 for (IGlass = 1; IGlass <= NGlass(IGlSys); ++IGlass) {
    4080           10 :                     auto *mat = new Material::MaterialGlass;
    4081           10 :                     mat->group = Material::Group::Glass;
    4082           20 :                     mat->Name = (NGlSys == 1) ? format("W5:{}:GLASS{}", DesiredConstructionName, NumName(IGlass))
    4083           10 :                                               : format("W5:{}:{}:GLASS{}", DesiredConstructionName, NumName(IGlSys), NumName(IGlass));
    4084              : 
    4085           10 :                     s_mat->materials.push_back(mat);
    4086           10 :                     mat->Num = s_mat->materials.isize();
    4087           10 :                     s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    4088              : 
    4089           10 :                     MaterNumSysGlass(IGlass, IGlSys) = mat->Num;
    4090              : 
    4091           10 :                     NextLine = W5DataFile.readLine();
    4092           10 :                     ++FileLineCount;
    4093              : 
    4094           10 :                     readList(NextLine.data.substr(25),
    4095           10 :                              mat->Thickness,
    4096           10 :                              mat->Conductivity,
    4097           10 :                              mat->Trans,
    4098           10 :                              mat->ReflectSolBeamFront,
    4099           10 :                              mat->ReflectSolBeamBack,
    4100           10 :                              mat->TransVis,
    4101           10 :                              mat->ReflectVisBeamFront,
    4102           10 :                              mat->ReflectVisBeamBack,
    4103           10 :                              mat->TransThermal,
    4104           10 :                              mat->AbsorpThermalFront,
    4105           10 :                              mat->AbsorpThermalBack,
    4106              :                              LayerName);
    4107              : 
    4108           10 :                     mat->Thickness *= 0.001;
    4109           10 :                     if (mat->Thickness <= 0.0) {
    4110              :                     }
    4111           10 :                     mat->Roughness = Material::SurfaceRoughness::VerySmooth;
    4112           10 :                     mat->AbsorpThermal = mat->AbsorpThermalBack;
    4113           10 :                     if (mat->Thickness <= 0.0) {
    4114            0 :                         ShowSevereError(state,
    4115            0 :                                         format("SearchWindow5DataFile: Material=\"{}\" has thickness of 0.0.  Will be set to thickness = .001 but "
    4116              :                                                "inaccuracies may result.",
    4117            0 :                                                mat->Name));
    4118            0 :                         ShowContinueError(state, format("Line being read={}", NextLine.data));
    4119            0 :                         ShowContinueError(state, format("Thickness field starts at column 26={}", NextLine.data.substr(25)));
    4120            0 :                         mat->Thickness = 0.001;
    4121              :                     }
    4122              :                 }
    4123              :             }
    4124              : 
    4125              :             // Gap objects
    4126            5 :             NextLine = W5DataFile.readLine();
    4127            5 :             if (NextLine.eof) {
    4128            0 :                 goto Label1000;
    4129              :             }
    4130            5 :             ++FileLineCount;
    4131           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4132           10 :                 for (IGap = 1; IGap <= NGaps(IGlSys); ++IGap) {
    4133            5 :                     auto *matGas = new Material::MaterialGasMix;
    4134           10 :                     matGas->Name = (NGlSys == 1) ? format("W5:{}:GAP{}", DesiredConstructionName, NumName(IGap))
    4135            5 :                                                  : format("W5:{}:{}:GAP{}", DesiredConstructionName, NumName(IGlSys), NumName(IGap));
    4136            5 :                     s_mat->materials.push_back(matGas);
    4137            5 :                     matGas->Num = s_mat->materials.isize();
    4138            5 :                     s_mat->materialMap.insert_or_assign(matGas->Name, matGas->Num);
    4139              : 
    4140            5 :                     MaterNumSysGap(IGap, IGlSys) = matGas->Num;
    4141            5 :                     NextLine = W5DataFile.readLine();
    4142            5 :                     ++FileLineCount;
    4143            5 :                     readList(NextLine.data.substr(23), matGas->Thickness, NumGases(IGap, IGlSys));
    4144            5 :                     matGas->Thickness *= 0.001;
    4145            5 :                     matGas->Roughness = Material::SurfaceRoughness::MediumRough; // Unused
    4146              :                 }
    4147              :             }
    4148              : 
    4149              :             // Gap/gas materials are read in multiple passes
    4150            5 :             NextLine = W5DataFile.readLine();
    4151            5 :             if (NextLine.eof) {
    4152            0 :                 goto Label1000; // Exsqueeze me?
    4153              :             }
    4154            5 :             ++FileLineCount;
    4155           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4156           10 :                 for (IGap = 1; IGap <= NGaps(IGlSys); ++IGap) {
    4157            5 :                     int matNum = MaterNumSysGap(IGap, IGlSys);
    4158            5 :                     auto *matGas = dynamic_cast<Material::MaterialGasMix *>(s_mat->materials(matNum));
    4159            5 :                     assert(matGas != nullptr);
    4160            5 :                     matGas->numGases = NumGases(IGap, IGlSys);
    4161           10 :                     for (int IGas = 0; IGas < matGas->numGases; ++IGas) {
    4162            5 :                         auto &gas = matGas->gases[IGas];
    4163            5 :                         NextLine = W5DataFile.readLine();
    4164            5 :                         ++FileLineCount;
    4165            5 :                         readList(NextLine.data.substr(19),
    4166              :                                  GasName(IGas + 1),
    4167            5 :                                  matGas->gasFracts[IGas],
    4168            5 :                                  gas.wght,
    4169            5 :                                  gas.con.c0,
    4170            5 :                                  gas.con.c1,
    4171            5 :                                  gas.con.c2,
    4172            5 :                                  gas.vis.c0,
    4173            5 :                                  gas.vis.c1,
    4174            5 :                                  gas.vis.c2,
    4175            5 :                                  gas.cp.c0,
    4176            5 :                                  gas.cp.c1,
    4177            5 :                                  gas.cp.c2);
    4178              :                     }
    4179              :                     // Nominal resistance of gap at room temperature (based on first gas in mixture)
    4180            5 :                     auto const &gas0 = matGas->gases[0];
    4181            5 :                     matGas->NominalR = matGas->Thickness / (gas0.con.c0 + gas0.con.c1 * 300.0 + gas0.con.c2 * 90000.0);
    4182              :                 }
    4183              :             }
    4184              : 
    4185              :             // Construction objects
    4186              : 
    4187              :             // reallocate Construct types
    4188            5 :             state.dataHeatBal->TotConstructs += NGlSys;
    4189            5 :             state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
    4190            5 :             state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
    4191            5 :             state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
    4192            5 :             state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
    4193            5 :             state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
    4194              : 
    4195              :             // these Construct arrays dimensioned based on MaxSolidWinLayers
    4196           10 :             for (int i = (state.dataHeatBal->TotConstructs - NGlSys + 1); i <= state.dataHeatBal->TotConstructs; ++i) {
    4197            5 :                 auto &e = state.dataConstruction->Construct(i);
    4198            5 :                 e.setArraysBasedOnMaxSolidWinLayers(state);
    4199              :             }
    4200              : 
    4201            5 :             NextLine = W5DataFile.readLine();
    4202            5 :             if (NextLine.eof) {
    4203            0 :                 goto Label1000;
    4204              :             }
    4205            5 :             ++FileLineCount;
    4206              : 
    4207              :             // When pulling in develop, the following two blocks appear to have been modified in develop,
    4208              :             //  but removed entirely in this branch.  I'm going to leave them commented.
    4209              :             // Pre-calculate constants
    4210              :             // for (IPhi = 1; IPhi <= 10; ++IPhi) {
    4211              :             //     CosPhiIndepVar(IPhi) = std::cos((IPhi - 1) * 10.0 * Constant::DegToRad);
    4212              :             //}
    4213              : 
    4214              :             // Pre-calculate constants
    4215              :             // for (IPhi = 1; IPhi <= 10; ++IPhi) {
    4216              :             //    Phi = double(IPhi - 1) * 10.0;
    4217              :             //    CosPhi(IPhi) = std::cos(Phi * Constant::DegToRad);
    4218              :             //    if (std::abs(CosPhi(IPhi)) < 0.0001) CosPhi(IPhi) = 0.0;
    4219              :             //}
    4220              : 
    4221           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4222            5 :                 ConstrNum = state.dataHeatBal->TotConstructs - NGlSys + IGlSys;
    4223            5 :                 auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    4224            5 :                 if (IGlSys == 1) {
    4225            5 :                     thisConstruct.Name = DesiredConstructionName;
    4226              :                 } else {
    4227            0 :                     thisConstruct.Name = DesiredConstructionName + ":2";
    4228              :                 }
    4229           60 :                 for (loop = 1; loop <= Construction::MaxLayersInConstruct; ++loop) {
    4230           55 :                     thisConstruct.LayerPoint(loop) = 0;
    4231              :                 }
    4232            5 :                 thisConstruct.InsideAbsorpSolar = 0.0;
    4233            5 :                 thisConstruct.OutsideAbsorpSolar = 0.0;
    4234            5 :                 thisConstruct.DayltPropPtr = 0;
    4235            5 :                 thisConstruct.CTFCross.fill(0.0);
    4236            5 :                 thisConstruct.CTFFlux.fill(0.0);
    4237            5 :                 thisConstruct.CTFInside.fill(0.0);
    4238            5 :                 thisConstruct.CTFOutside.fill(0.0);
    4239            5 :                 thisConstruct.CTFSourceIn.fill(0.0);
    4240            5 :                 thisConstruct.CTFSourceOut.fill(0.0);
    4241            5 :                 thisConstruct.CTFTimeStep = 0.0;
    4242            5 :                 thisConstruct.CTFTSourceOut.fill(0.0);
    4243            5 :                 thisConstruct.CTFTSourceIn.fill(0.0);
    4244            5 :                 thisConstruct.CTFTSourceQ.fill(0.0);
    4245            5 :                 thisConstruct.CTFTUserOut.fill(0.0);
    4246            5 :                 thisConstruct.CTFTUserIn.fill(0.0);
    4247            5 :                 thisConstruct.CTFTUserSource.fill(0.0);
    4248            5 :                 thisConstruct.NumHistories = 0;
    4249            5 :                 thisConstruct.NumCTFTerms = 0;
    4250            5 :                 thisConstruct.UValue = 0.0;
    4251            5 :                 thisConstruct.SourceSinkPresent = false;
    4252            5 :                 thisConstruct.SolutionDimensions = 0;
    4253            5 :                 thisConstruct.SourceAfterLayer = 0;
    4254            5 :                 thisConstruct.TempAfterLayer = 0;
    4255            5 :                 thisConstruct.ThicknessPerpend = 0.0;
    4256            5 :                 thisConstruct.AbsDiff = 0.0;
    4257            5 :                 thisConstruct.AbsDiffBack = 0.0;
    4258            5 :                 thisConstruct.AbsDiffShade = 0.0;
    4259            5 :                 thisConstruct.AbsDiffBackShade = 0.0;
    4260            5 :                 thisConstruct.ShadeAbsorpThermal = 0.0;
    4261            5 :                 std::fill(thisConstruct.AbsBeamShadeCoef.begin(), thisConstruct.AbsBeamShadeCoef.end(), 0.0);
    4262            5 :                 thisConstruct.AbsDiffIn = 0.0;
    4263            5 :                 thisConstruct.AbsDiffOut = 0.0;
    4264            5 :                 thisConstruct.TransDiff = 0.0;
    4265            5 :                 thisConstruct.TransDiffVis = 0.0;
    4266            5 :                 thisConstruct.ReflectSolDiffBack = 0.0;
    4267            5 :                 thisConstruct.ReflectSolDiffFront = 0.0;
    4268            5 :                 thisConstruct.ReflectVisDiffBack = 0.0;
    4269            5 :                 thisConstruct.ReflectVisDiffFront = 0.0;
    4270            5 :                 std::fill(thisConstruct.TransSolBeamCoef.begin(), thisConstruct.TransSolBeamCoef.end(), 0.0);
    4271            5 :                 std::fill(thisConstruct.TransVisBeamCoef.begin(), thisConstruct.TransVisBeamCoef.end(), 0.0);
    4272            5 :                 std::fill(thisConstruct.ReflSolBeamFrontCoef.begin(), thisConstruct.ReflSolBeamFrontCoef.end(), 0.0);
    4273            5 :                 std::fill(thisConstruct.ReflSolBeamBackCoef.begin(), thisConstruct.ReflSolBeamBackCoef.end(), 0.0);
    4274            5 :                 thisConstruct.W5FrameDivider = 0;
    4275            5 :                 thisConstruct.TotLayers = NGlass(IGlSys) + NGaps(IGlSys);
    4276            5 :                 thisConstruct.TotGlassLayers = NGlass(IGlSys);
    4277            5 :                 thisConstruct.TotSolidLayers = NGlass(IGlSys);
    4278              : 
    4279           40 :                 for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
    4280           35 :                     std::fill(thisConstruct.AbsBeamCoef(Layer).begin(), thisConstruct.AbsBeamCoef(Layer).end(), 0.0);
    4281           35 :                     std::fill(thisConstruct.AbsBeamBackCoef(Layer).begin(), thisConstruct.AbsBeamBackCoef(Layer).end(), 0.0);
    4282              :                 }
    4283              : 
    4284           15 :                 for (IGlass = 1; IGlass <= NGlass(IGlSys); ++IGlass) {
    4285           10 :                     thisConstruct.LayerPoint(2 * IGlass - 1) = MaterNumSysGlass(IGlass, IGlSys);
    4286           10 :                     if (IGlass < NGlass(IGlSys)) {
    4287            5 :                         thisConstruct.LayerPoint(2 * IGlass) = MaterNumSysGap(IGlass, IGlSys);
    4288              :                     }
    4289              :                 }
    4290              : 
    4291            5 :                 thisConstruct.OutsideRoughness = Material::SurfaceRoughness::VerySmooth;
    4292            5 :                 thisConstruct.InsideAbsorpThermal = s_mat->materials(thisConstruct.LayerPoint(thisConstruct.TotLayers))->AbsorpThermalBack;
    4293            5 :                 thisConstruct.OutsideAbsorpThermal = s_mat->materials(thisConstruct.LayerPoint(1))->AbsorpThermalFront;
    4294            5 :                 thisConstruct.TypeIsWindow = true;
    4295            5 :                 thisConstruct.FromWindow5DataFile = true;
    4296            5 :                 thisConstruct.W5FileGlazingSysHeight = WinHeight(IGlSys);
    4297            5 :                 thisConstruct.W5FileGlazingSysWidth = WinWidth(IGlSys);
    4298              : 
    4299            5 :                 thisConstruct.W5FileMullionOrientation = static_cast<DataWindowEquivalentLayer::Orientation>(
    4300            5 :                     getEnumValue(DataWindowEquivalentLayer::orientationNamesUC, MullionOrientation));
    4301              : 
    4302            5 :                 thisConstruct.W5FileMullionWidth = MullionWidth;
    4303              : 
    4304              :                 // Fill Construct with system transmission, reflection and absorption properties
    4305              : 
    4306            5 :                 NextLine = W5DataFile.readLine();
    4307            5 :                 if (NextLine.eof) {
    4308            0 :                     goto Label1000;
    4309              :                 }
    4310            5 :                 ++FileLineCount;
    4311            5 :                 if (IGlSys == 1) {
    4312            5 :                     NextLine = W5DataFile.readLine();
    4313            5 :                     if (NextLine.eof) {
    4314            0 :                         goto Label1000;
    4315              :                     }
    4316            5 :                     ++FileLineCount;
    4317              :                 }
    4318            5 :                 NextLine = W5DataFile.readLine();
    4319            5 :                 if (NextLine.eof) {
    4320            0 :                     goto Label1000;
    4321              :                 }
    4322            5 :                 ++FileLineCount;
    4323            5 :                 if (!readItem(NextLine.data.substr(5), TsolTemp)) {
    4324            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of TSol values.");
    4325            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount, NextLine.data.substr(0, 100)));
    4326            0 :                     ErrorsFound = true;
    4327            5 :                 } else if (any_lt(TsolTemp, 0.0) || any_gt(TsolTemp, 1.0)) {
    4328            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of TSol values. (out of range [0,1])");
    4329            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount, NextLine.data.substr(0, 100)));
    4330            0 :                     ErrorsFound = true;
    4331              :                 }
    4332              : 
    4333           15 :                 for (IGlass = 1; IGlass <= NGlass(IGlSys); ++IGlass) {
    4334           10 :                     NextLine = W5DataFile.readLine();
    4335           10 :                     ++FileLineCount;
    4336           10 :                     if (!readItem(NextLine.data.substr(5), AbsSolTemp(IGlass, _))) {
    4337            0 :                         ShowSevereError(state,
    4338            0 :                                         format("HeatBalanceManager: SearchWindow5DataFile: Error in Read of AbsSol values. For Glass={}", IGlass));
    4339            0 :                         ShowContinueError(state,
    4340            0 :                                           format("Line (~{}) in error (first 100 characters)={}", FileLineCount, NextLine.data.substr(0, 100)));
    4341            0 :                         ErrorsFound = true;
    4342           10 :                     } else if (any_lt(AbsSolTemp(IGlass, _), 0.0) || any_gt(AbsSolTemp(IGlass, _), 1.0)) {
    4343            0 :                         ShowSevereError(
    4344              :                             state,
    4345            0 :                             format("HeatBalanceManager: SearchWindow5DataFile: Error in Read of AbsSol values. (out of range [0,1]) For Glass={}",
    4346              :                                    IGlass));
    4347            0 :                         ShowContinueError(state,
    4348            0 :                                           format("Line (~{}) in error (first 100 characters)={}", FileLineCount, NextLine.data.substr(0, 100)));
    4349            0 :                         ErrorsFound = true;
    4350              :                     }
    4351              :                 }
    4352           30 :                 for (ILine = 1; ILine <= 5; ++ILine) {
    4353           25 :                     NextLine = W5DataFile.readLine();
    4354           25 :                     DataLine(ILine) = NextLine.data;
    4355              :                 }
    4356              : 
    4357            5 :                 if (!readItem(DataLine(1).substr(5), RfsolTemp)) {
    4358            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of RfSol values.");
    4359            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 1, DataLine(1).substr(0, 100)));
    4360            0 :                     ErrorsFound = true;
    4361            5 :                 } else if (any_lt(RfsolTemp, 0.0) || any_gt(RfsolTemp, 1.0)) {
    4362            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of RfSol values. (out of range [0,1])");
    4363            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 1, DataLine(1).substr(0, 100)));
    4364            0 :                     ErrorsFound = true;
    4365              :                 }
    4366              : 
    4367            5 :                 if (!readItem(DataLine(2).substr(5), RbsolTemp)) {
    4368            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of RbSol values.");
    4369            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 2, DataLine(2).substr(0, 100)));
    4370            0 :                     ErrorsFound = true;
    4371            5 :                 } else if (any_lt(RbsolTemp, 0.0) || any_gt(RbsolTemp, 1.0)) {
    4372            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of RbSol values. (out of range [0,1])");
    4373            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 2, DataLine(2).substr(0, 100)));
    4374            0 :                     ErrorsFound = true;
    4375              :                 }
    4376            5 :                 if (!readItem(DataLine(3).substr(5), TvisTemp)) {
    4377            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Tvis values.");
    4378            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 3, DataLine(3).substr(0, 100)));
    4379            0 :                     ErrorsFound = true;
    4380            5 :                 } else if (any_lt(TvisTemp, 0.0) || any_gt(TvisTemp, 1.0)) {
    4381            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Tvis values. (out of range [0,1])");
    4382            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 3, DataLine(3).substr(0, 100)));
    4383            0 :                     ErrorsFound = true;
    4384              :                 }
    4385            5 :                 if (!readItem(DataLine(4).substr(5), RfvisTemp)) {
    4386            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Rfvis values.");
    4387            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 4, DataLine(4).substr(0, 100)));
    4388            0 :                     ErrorsFound = true;
    4389            5 :                 } else if (any_lt(RfvisTemp, 0.0) || any_gt(RfvisTemp, 1.0)) {
    4390            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Rfvis values. (out of range [0,1])");
    4391            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 4, DataLine(4).substr(0, 100)));
    4392            0 :                     ErrorsFound = true;
    4393              :                 }
    4394            5 :                 if (!readItem(DataLine(5).substr(5), RbvisTemp)) {
    4395            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Rbvis values.");
    4396            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 5, DataLine(5).substr(0, 100)));
    4397            0 :                     ErrorsFound = true;
    4398            5 :                 } else if (any_lt(RbvisTemp, 0.0) || any_gt(RbvisTemp, 1.0)) {
    4399            0 :                     ShowSevereError(state, "HeatBalanceManager: SearchWindow5DataFile: Error in Read of Rbvis values. (out of range [0,1])");
    4400            0 :                     ShowContinueError(state, format("Line (~{}) in error (first 100 characters)={}", FileLineCount + 5, DataLine(5).substr(0, 100)));
    4401            0 :                     ErrorsFound = true;
    4402              :                 }
    4403            5 :                 FileLineCount += 5;
    4404              : 
    4405            5 :                 if (ErrorsFound) {
    4406            0 :                     ShowFatalError(
    4407              :                         state,
    4408            0 :                         format("HeatBalanceManager: SearchWindow5DataFile: Construction={} from the Window5 data file cannot be used because "
    4409              :                                "of above errors",
    4410              :                                DesiredConstructionName));
    4411              :                 }
    4412              : 
    4413           55 :                 for (int iPhi = 0; iPhi < Window::numPhis; ++iPhi) {
    4414           50 :                     Tsol[iPhi] = TsolTemp(iPhi + 1);
    4415           50 :                     Tvis[iPhi] = TvisTemp(iPhi + 1);
    4416           50 :                     Rfsol[iPhi] = RfsolTemp(iPhi + 1);
    4417           50 :                     Rbsol[iPhi] = RbsolTemp(iPhi + 1);
    4418           50 :                     Rfvis[iPhi] = RfvisTemp(iPhi + 1);
    4419           50 :                     Rbvis[iPhi] = RbvisTemp(iPhi + 1);
    4420              :                 }
    4421              : 
    4422           15 :                 for (IGlass = 1; IGlass <= NGlass(IGlSys); ++IGlass) {
    4423          110 :                     for (int iPhi = 0; iPhi < Window::numPhis; ++iPhi) {
    4424          100 :                         AbsSol(IGlass)[iPhi] = AbsSolTemp(IGlass, iPhi + 1);
    4425              :                     }
    4426              :                 }
    4427              : 
    4428              :                 // Hemis
    4429            5 :                 thisConstruct.TransDiff = TsolTemp(11);
    4430            5 :                 thisConstruct.TransDiffVis = TvisTemp(11);
    4431            5 :                 thisConstruct.ReflectSolDiffFront = RfsolTemp(11);
    4432            5 :                 thisConstruct.ReflectSolDiffBack = RbsolTemp(11);
    4433            5 :                 thisConstruct.ReflectVisDiffFront = RfvisTemp(11);
    4434            5 :                 thisConstruct.ReflectVisDiffBack = RbvisTemp(11);
    4435              : 
    4436              :                 // Using pre-calculated/hard-coded cosPhis in this module is okay.  Shrug.
    4437            5 :                 Window::W5LsqFit(Window::cosPhis, Tsol, thisConstruct.TransSolBeamCoef);
    4438            5 :                 Window::W5LsqFit(Window::cosPhis, Tvis, thisConstruct.TransVisBeamCoef);
    4439            5 :                 Window::W5LsqFit(Window::cosPhis, Rfsol, thisConstruct.ReflSolBeamFrontCoef);
    4440           15 :                 for (IGlass = 1; IGlass <= NGlass(IGlSys); ++IGlass) {
    4441           10 :                     Window::W5LsqFit(Window::cosPhis, AbsSol(IGlass), thisConstruct.AbsBeamCoef(IGlass));
    4442              :                 }
    4443              : 
    4444              :                 // For comparing fitted vs. input distribution in incidence angle
    4445           55 :                 for (int iPhi = 0; iPhi < Window::numPhis; ++iPhi) {
    4446           50 :                     tsolFit[iPhi] = Window::POLYF(Window::cosPhis[iPhi], thisConstruct.TransSolBeamCoef);
    4447           50 :                     tvisFit[iPhi] = Window::POLYF(Window::cosPhis[iPhi], thisConstruct.TransVisBeamCoef);
    4448           50 :                     rfsolFit[iPhi] = Window::POLYF(Window::cosPhis[iPhi], thisConstruct.ReflSolBeamFrontCoef);
    4449          150 :                     for (IGlass = 1; IGlass <= NGlass(IGlSys); ++IGlass) {
    4450          100 :                         solabsFit(IGlass)[iPhi] = Window::POLYF(Window::cosPhis[iPhi], thisConstruct.AbsBeamCoef(IGlass));
    4451              :                     }
    4452              :                 }
    4453              :                 // end
    4454              : 
    4455              :                 // NominalRforNominalUCalculation of this construction (actually the total resistance of all of its layers; gas layer
    4456              :                 // conductivity here ignores convective effects in gap.)
    4457            5 :                 state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) = 0.0;
    4458           20 :                 for (loop = 1; loop <= NGlass(IGlSys) + NGaps(IGlSys); ++loop) {
    4459           15 :                     int matNum = thisConstruct.LayerPoint(loop);
    4460           15 :                     auto const *matBase = s_mat->materials(matNum);
    4461           15 :                     assert(matBase != nullptr);
    4462           15 :                     if (matBase->group == Material::Group::Glass) {
    4463           10 :                         state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) += matBase->Thickness / matBase->Conductivity;
    4464            5 :                     } else if (matBase->group == Material::Group::Gas || matBase->group == Material::Group::GasMixture) {
    4465            5 :                         auto const *matGas = dynamic_cast<Material::MaterialGasMix const *>(matBase);
    4466            5 :                         assert(matGas != nullptr);
    4467              : 
    4468              :                         // If mixture, use conductivity of first gas in mixture
    4469            5 :                         state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) +=
    4470            5 :                             matGas->Thickness / (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
    4471              :                     }
    4472              :                 }
    4473              : 
    4474              :             } // End of loop over glazing systems
    4475              : 
    4476              :             // WindowFrameAndDivider objects
    4477              : 
    4478            5 :             TotFrameDividerPrev = state.dataHeatBal->TotFrameDivider;
    4479           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4480            5 :                 if (FrameWidth > 0.0 || DividerWidth(IGlSys) > 0.0) {
    4481            5 :                     ++state.dataHeatBal->TotFrameDivider;
    4482            5 :                     state.dataConstruction->Construct(state.dataHeatBal->TotConstructs - NGlSys + IGlSys).W5FrameDivider =
    4483            5 :                         state.dataHeatBal->TotFrameDivider;
    4484              :                 }
    4485              :             }
    4486              : 
    4487            5 :             if (state.dataHeatBal->TotFrameDivider > TotFrameDividerPrev) {
    4488            5 :                 state.dataSurface->FrameDivider.redimension(state.dataHeatBal->TotFrameDivider);
    4489              :             }
    4490              : 
    4491           10 :             for (IGlSys = 1; IGlSys <= NGlSys; ++IGlSys) {
    4492            5 :                 if (FrameWidth > 0.0 || DividerWidth(IGlSys) > 0.0) {
    4493            5 :                     FrDivNum = state.dataConstruction->Construct(state.dataHeatBal->TotConstructs - NGlSys + IGlSys).W5FrameDivider;
    4494            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameWidth = FrameWidth;
    4495            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameProjectionOut = FrameProjectionOut;
    4496            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameProjectionIn = FrameProjectionIn;
    4497            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameConductance = FrameConductance;
    4498            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrEdgeToCenterGlCondRatio = FrEdgeToCenterGlCondRatio;
    4499            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameSolAbsorp = FrameSolAbsorp;
    4500            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameVisAbsorp = FrameVisAbsorp;
    4501            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameEmis = FrameEmis;
    4502            5 :                     state.dataSurface->FrameDivider(FrDivNum).FrameEdgeWidth = 0.06355; // 2.5 in
    4503              : 
    4504            5 :                     state.dataSurface->FrameDivider(FrDivNum).MullionOrientation = static_cast<DataWindowEquivalentLayer::Orientation>(
    4505            5 :                         getEnumValue(DataWindowEquivalentLayer::orientationNamesUC, MullionOrientation));
    4506              : 
    4507            5 :                     if (Util::SameString(DividerType(IGlSys), "DividedLite")) {
    4508            0 :                         state.dataSurface->FrameDivider(FrDivNum).DividerType = DataSurfaces::FrameDividerType::DividedLite;
    4509            5 :                     } else if (Util::SameString(DividerType(IGlSys), "Suspended")) {
    4510            5 :                         state.dataSurface->FrameDivider(FrDivNum).DividerType = DataSurfaces::FrameDividerType::Suspended;
    4511              :                     }
    4512            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerWidth = DividerWidth(IGlSys);
    4513            5 :                     state.dataSurface->FrameDivider(FrDivNum).HorDividers = HorDividers(IGlSys);
    4514            5 :                     state.dataSurface->FrameDivider(FrDivNum).VertDividers = VertDividers(IGlSys);
    4515            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerProjectionOut = DividerProjectionOut(IGlSys);
    4516            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerProjectionIn = DividerProjectionIn(IGlSys);
    4517            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerConductance = DividerConductance(IGlSys);
    4518            5 :                     state.dataSurface->FrameDivider(FrDivNum).DivEdgeToCenterGlCondRatio = DivEdgeToCenterGlCondRatio(IGlSys);
    4519            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerSolAbsorp = DividerSolAbsorp(IGlSys);
    4520            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerVisAbsorp = DividerVisAbsorp(IGlSys);
    4521            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerEmis = DividerEmis(IGlSys);
    4522            5 :                     state.dataSurface->FrameDivider(FrDivNum).DividerEdgeWidth = 0.06355; // 2.5 in
    4523            5 :                     if (NGlSys == 1) {
    4524            5 :                         state.dataSurface->FrameDivider(FrDivNum).Name = "W5:" + DesiredConstructionName;
    4525              :                     } else {
    4526            0 :                         state.dataSurface->FrameDivider(FrDivNum).Name = "W5:" + DesiredConstructionName + ':' + NumName(IGlSys);
    4527              :                     }
    4528              :                 }
    4529              :             }
    4530              : 
    4531            5 :             if (FrameWidth > 0.0 && DividerWidth(1) > 0.0) {
    4532            5 :                 DisplayString(state, "--Construction and associated frame and divider found");
    4533            0 :             } else if (FrameWidth > 0.0) {
    4534            0 :                 DisplayString(state, "--Construction and associated frame found");
    4535            0 :             } else if (DividerWidth(1) > 0.0) {
    4536            0 :                 DisplayString(state, "--Construction and associated divider found");
    4537              :             } else {
    4538            0 :                 DisplayString(state, "--Construction without frame or divider found");
    4539              :             }
    4540              :         }
    4541              : 
    4542            5 :         return;
    4543              : 
    4544            0 :     Label1000:;
    4545            0 :         EOFonFile = true;
    4546          205 :     }
    4547              : 
    4548           16 :     void SetStormWindowControl(EnergyPlusData &state)
    4549              :     {
    4550              : 
    4551              :         // SUBROUTINE INFORMATION:
    4552              :         //       AUTHOR         Fred Winkelmann
    4553              :         //       DATE WRITTEN   Jan 2004
    4554              : 
    4555              :         // PURPOSE OF THIS SUBROUTINE:
    4556              :         // Sets the storm window flag for each window, which is:
    4557              :         //  -1: if storm window is not applicable (this will always be the value for interior
    4558              :         //        windows since storm windows can only be applied to exterior windows
    4559              :         //   0: if the window has a storm window but it is off
    4560              :         //   1: if the window has a storm window and it is on
    4561              : 
    4562              :         // A "storm window" is a single layer of exterior glass separated from the main window by air gap.
    4563              :         // Whether the storm window is in place is determined by the following values, which
    4564              :         // which are specified in the Storm Window object for the window:
    4565              :         //  -Month that Storm Window Is Put On
    4566              :         //  -Day of Month that Storm Window Is Put On
    4567              :         //  -Month that Storm Window Is Taken Off
    4568              :         //  -Day of Month that Storm Window Is Taken Off
    4569              : 
    4570              :         int StormWinFlag; // Storm window flag; this routine sets the following values:
    4571              :         //   0: if the storm window is off this time step
    4572              :         //   1: if the storm window is on this time step
    4573              : 
    4574           16 :         state.dataHeatBal->StormWinChangeThisDay = false;
    4575              : 
    4576           32 :         for (int StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
    4577           16 :             int SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum;
    4578           16 :             state.dataSurface->SurfWinStormWinFlagPrevDay(SurfNum) = state.dataSurface->SurfWinStormWinFlag(SurfNum);
    4579           16 :             int DateOff = state.dataSurface->StormWindow(StormWinNum).DateOff - 1;
    4580              :             // Note: Dateon = Dateoff is not allowed and will have produced an error in getinput.
    4581           16 :             if (DateOff == 0) {
    4582            0 :                 DateOff = 366;
    4583              :             }
    4584           16 :             if (General::BetweenDates(state.dataEnvrn->DayOfYear_Schedule, state.dataSurface->StormWindow(StormWinNum).DateOn, DateOff)) {
    4585            8 :                 StormWinFlag = 1;
    4586              :             } else {
    4587            8 :                 StormWinFlag = 0;
    4588              :             }
    4589           16 :             state.dataSurface->SurfWinStormWinFlag(SurfNum) = StormWinFlag;
    4590           16 :             if (state.dataGlobal->BeginSimFlag) {
    4591            1 :                 state.dataSurface->SurfWinStormWinFlagPrevDay(SurfNum) = StormWinFlag;
    4592              :             }
    4593           16 :             if (state.dataSurface->SurfWinStormWinFlag(SurfNum) != state.dataSurface->SurfWinStormWinFlagPrevDay(SurfNum)) {
    4594            3 :                 state.dataHeatBal->StormWinChangeThisDay = true;
    4595              :             }
    4596              :         }
    4597           16 :     }
    4598              : 
    4599           21 :     void CreateFCfactorConstructions(EnergyPlusData &state,
    4600              :                                      int &ConstrNum,   // Counter for Constructions
    4601              :                                      bool &ErrorsFound // If errors found in input
    4602              :     )
    4603              :     {
    4604              : 
    4605              :         // SUBROUTINE INFORMATION:
    4606              :         //       AUTHOR         Tianzhen Hong
    4607              :         //       DATE WRITTEN   July 2009
    4608              : 
    4609              :         // PURPOSE OF THIS SUBROUTINE:
    4610              :         // This subroutine goes through each construction defined with Ffactor or Cfactor method,
    4611              :         // and creates a construction (concrete + insulation) used in the heat transfer calculation.
    4612              :         // This subroutine only gets called once in the GetConstructionData subroutine
    4613              : 
    4614              :         // ASHRAE Handbook Fundamental 2005
    4615              :         // Thermal resistance of the inside air film, m2.K/W. Average of 0.16 (heat flow down) and 0.11 (heat flow up)
    4616           21 :         Real64 constexpr Rfilm_in(0.135);
    4617              :         // Thermal resistance of the outside air film used in calculating the Ffactor, m2.K/W. 0.17/5.678
    4618           21 :         Real64 constexpr Rfilm_out(0.03);
    4619              : 
    4620              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4621              :         int ConstructNumAlpha;             // Number of construction alpha names being passed
    4622              :         int DummyNumProp;                  // dummy variable for properties being passed
    4623              :         int IOStat;                        // IO Status when calling get input subroutine
    4624           21 :         Array1D_string ConstructAlphas(1); // Construction Alpha names defined
    4625           21 :         Array1D<Real64> DummyProps(4);     // Temporary array to transfer construction properties
    4626              : 
    4627              :         int TotFfactorConstructs; // Number of slabs-on-grade or underground floor constructions defined with F factors
    4628              :         int TotCfactorConstructs; // Number of underground wall constructions defined with C factors
    4629              : 
    4630              :         Real64 Ffactor;          // Ffactor in W/m-K, applies to deltaT of outside - indoor air temperature
    4631              :         Real64 Cfactor;          // Cfactor in W/m2-K, does not include soil or air films
    4632              :         Real64 Area;             // floor area in m2
    4633              :         Real64 PerimeterExposed; // perimeter exposed in m
    4634              :         Real64 Height;           // Height of the underground wall in m
    4635              : 
    4636              :         Real64 Reff;          // Effective thermal resistance, m2.K/W
    4637              :         Real64 Rcon;          // Concrete layer thermal resistance, m2.K/W
    4638              :         Real64 Rfic;          // Thermal resistance of the fictitious material, m2.K/W
    4639              :         Real64 Rsoilequ;      // Effective R-value of soil for underground walls
    4640              :         int iFCConcreteLayer; // Layer pointer to the materials array
    4641              : 
    4642           21 :         auto &s_mat = state.dataMaterial;
    4643              :         // First get the concrete layer
    4644           21 :         iFCConcreteLayer = Material::GetMaterialNum(state, "~FC_CONCRETE");
    4645           21 :         Rcon = s_mat->materials(iFCConcreteLayer)->Resistance;
    4646              : 
    4647              :         // Count number of constructions defined with Ffactor or Cfactor method
    4648           21 :         TotFfactorConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:FfactorGroundFloor");
    4649           21 :         TotCfactorConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Construction:CfactorUndergroundWall");
    4650              : 
    4651           21 :         if (TotFfactorConstructs > 0) {
    4652           15 :             state.dataHeatBal->NoFfactorConstructionsUsed = false;
    4653              :         }
    4654              : 
    4655           21 :         if (TotCfactorConstructs > 0) {
    4656            7 :             state.dataHeatBal->NoCfactorConstructionsUsed = false;
    4657              :         }
    4658              : 
    4659              :         // First create ground floor constructions defined with F factor method if any
    4660           21 :         state.dataHeatBalMgr->CurrentModuleObject = "Construction:FfactorGroundFloor";
    4661              : 
    4662              :         // Loop through all constructs defined with Ffactor method
    4663          204 :         for (int Loop = 1; Loop <= TotFfactorConstructs; ++Loop) {
    4664              : 
    4665              :             // Get the object names for each construction from the input processor
    4666          549 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4667          183 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    4668              :                                                                      Loop,
    4669              :                                                                      ConstructAlphas,
    4670              :                                                                      ConstructNumAlpha,
    4671              :                                                                      DummyProps,
    4672              :                                                                      DummyNumProp,
    4673              :                                                                      IOStat,
    4674          183 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    4675          183 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    4676          183 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    4677          183 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    4678          366 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    4679          183 :                                                          state.dataHeatBalMgr->UniqueConstructNames,
    4680          183 :                                                          ConstructAlphas(1),
    4681          183 :                                                          state.dataHeatBalMgr->CurrentModuleObject,
    4682          183 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    4683              :                                                          ErrorsFound)) {
    4684            0 :                 continue;
    4685              :             }
    4686              : 
    4687          183 :             ++ConstrNum;
    4688              : 
    4689          183 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    4690          183 :             thisConstruct.Name = ConstructAlphas(1);
    4691          183 :             thisConstruct.TypeIsFfactorFloor = true;
    4692              : 
    4693          183 :             Ffactor = DummyProps(1);
    4694          183 :             Area = DummyProps(2);
    4695          183 :             PerimeterExposed = DummyProps(3);
    4696              : 
    4697          183 :             thisConstruct.Area = Area;
    4698          183 :             thisConstruct.PerimeterExposed = PerimeterExposed;
    4699          183 :             thisConstruct.FFactor = Ffactor;
    4700              : 
    4701          183 :             if (Ffactor <= 0.0) {
    4702            0 :                 ShowSevereError(state,
    4703            0 :                                 format("{}=\"{}\" has {} <= 0.0, must be > 0.0.",
    4704            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
    4705              :                                        ConstructAlphas(1),
    4706            0 :                                        state.dataIPShortCut->cNumericFieldNames(1)));
    4707            0 :                 ShowContinueError(state, format("Entered value=[{:.2R}]", Ffactor));
    4708            0 :                 ErrorsFound = true;
    4709              :             }
    4710              : 
    4711          183 :             if (Area <= 0.0) {
    4712            0 :                 ShowSevereError(state,
    4713            0 :                                 format("{}=\"{}\" has {} <= 0.0, must be > 0.0.",
    4714            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
    4715              :                                        ConstructAlphas(1),
    4716            0 :                                        state.dataIPShortCut->cNumericFieldNames(2)));
    4717            0 :                 ShowContinueError(state, format("Entered value=[{:.2R}]", Area));
    4718            0 :                 ErrorsFound = true;
    4719              :             }
    4720              : 
    4721          183 :             if (PerimeterExposed < 0.0) {
    4722            0 :                 ShowSevereError(state,
    4723            0 :                                 format("{}=\"{}\" has {} <= 0.0, must be > 0.0.",
    4724            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
    4725              :                                        ConstructAlphas(1),
    4726            0 :                                        state.dataIPShortCut->cNumericFieldNames(3)));
    4727            0 :                 ShowContinueError(state, format("Entered value=[{:.2R}]", PerimeterExposed));
    4728            0 :                 ErrorsFound = true;
    4729              :             }
    4730              : 
    4731              :             // The construction has two layers which have been created in GetMaterialData
    4732          183 :             thisConstruct.TotLayers = 2;
    4733              : 
    4734              :             // The concrete is the inside layer
    4735          183 :             thisConstruct.LayerPoint(2) = iFCConcreteLayer;
    4736              : 
    4737              :             // The fictitious insulation is the outside layer
    4738          183 :             thisConstruct.LayerPoint(1) = Material::GetMaterialNum(state, format("~FC_INSULATION_{}", Loop));
    4739              : 
    4740              :             // Calculate the thermal resistance of the fictitious insulation layer
    4741              :             // effective thermal resistance excludes inside and outside air films
    4742          183 :             if (PerimeterExposed > 0.0) {
    4743          148 :                 Reff = Area / (PerimeterExposed * Ffactor) - Rfilm_in - Rfilm_out;
    4744              :             } else { // PerimeterExposed = 0 for underground floor, assume R-1000 (IP)
    4745           35 :                 Reff = 177.0;
    4746              :             }
    4747              : 
    4748          183 :             Rfic = Reff - Rcon;
    4749          183 :             if (Rfic <= 0.0) {
    4750            0 :                 ShowSevereError(
    4751              :                     state,
    4752            0 :                     format("{}=\"{}\" has calculated R value <= 0.0, must be > 0.0.", state.dataHeatBalMgr->CurrentModuleObject, ConstructAlphas(1)));
    4753            0 :                 ShowContinueError(state, format("Calculated value=[{:.2R}] Check definition.", Rfic));
    4754            0 :                 ErrorsFound = true;
    4755              :             }
    4756              : 
    4757          183 :             auto *mat = s_mat->materials(thisConstruct.LayerPoint(1));
    4758          183 :             mat->Resistance = mat->NominalR = Rfic;
    4759              : 
    4760              :             // excluding thermal resistance of inside or outside air film
    4761              :             // 1/Reff gets reported as the "U-Factor no Film" in the summary report Envelope Summary | Opaque Exterior
    4762          183 :             state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) = Reff;
    4763              :         }
    4764              : 
    4765              :         // Then create underground wall constructions defined with C factor method if any
    4766           21 :         state.dataHeatBalMgr->CurrentModuleObject = "Construction:CfactorUndergroundWall";
    4767              : 
    4768           55 :         for (int Loop = 1; Loop <= TotCfactorConstructs; ++Loop) { // Loop through all constructs defined with Ffactor method
    4769              : 
    4770              :             // Get the object names for each construction from the input processor
    4771          102 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4772           34 :                                                                      state.dataHeatBalMgr->CurrentModuleObject,
    4773              :                                                                      Loop,
    4774              :                                                                      ConstructAlphas,
    4775              :                                                                      ConstructNumAlpha,
    4776              :                                                                      DummyProps,
    4777              :                                                                      DummyNumProp,
    4778              :                                                                      IOStat,
    4779           34 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    4780           34 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    4781           34 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    4782           34 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    4783           68 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    4784           34 :                                                          state.dataHeatBalMgr->UniqueConstructNames,
    4785           34 :                                                          ConstructAlphas(1),
    4786           34 :                                                          state.dataHeatBalMgr->CurrentModuleObject,
    4787           34 :                                                          state.dataIPShortCut->cAlphaFieldNames(1),
    4788              :                                                          ErrorsFound)) {
    4789            0 :                 continue;
    4790              :             }
    4791              : 
    4792           34 :             ++ConstrNum;
    4793              : 
    4794           34 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    4795           34 :             thisConstruct.Name = ConstructAlphas(1);
    4796           34 :             thisConstruct.TypeIsCfactorWall = true;
    4797              : 
    4798           34 :             Cfactor = DummyProps(1);
    4799           34 :             Height = DummyProps(2);
    4800              : 
    4801           34 :             thisConstruct.Height = Height;
    4802           34 :             thisConstruct.CFactor = Cfactor;
    4803              : 
    4804           34 :             if (Cfactor <= 0.0) {
    4805            0 :                 ShowSevereError(state,
    4806            0 :                                 format("{} {} has {} <= 0.0, must be > 0.0.",
    4807            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
    4808              :                                        ConstructAlphas(1),
    4809            0 :                                        state.dataIPShortCut->cNumericFieldNames(1)));
    4810            0 :                 ShowContinueError(state, format("Entered value=[{:.2R}]", Cfactor));
    4811            0 :                 ErrorsFound = true;
    4812              :             }
    4813              : 
    4814           34 :             if (Height <= 0.0) {
    4815            0 :                 ShowSevereError(state,
    4816            0 :                                 format("{} {} has {} <= 0.0, must be > 0.0.",
    4817            0 :                                        state.dataHeatBalMgr->CurrentModuleObject,
    4818              :                                        ConstructAlphas(1),
    4819            0 :                                        state.dataIPShortCut->cNumericFieldNames(2)));
    4820            0 :                 ShowContinueError(state, format("Entered value=[{:.2R}]", Height));
    4821            0 :                 ErrorsFound = true;
    4822              :             }
    4823              : 
    4824              :             // The construction has two layers which have been created in GetMaterialData
    4825           34 :             thisConstruct.TotLayers = 2;
    4826              : 
    4827              :             // The concrete is the inside layer
    4828           34 :             thisConstruct.LayerPoint(2) = iFCConcreteLayer;
    4829              : 
    4830              :             // The fictitious insulation is the outside layer
    4831           34 :             thisConstruct.LayerPoint(1) = Material::GetMaterialNum(state, format("~FC_INSULATION_{}", Loop + TotFfactorConstructs));
    4832              : 
    4833              :             // CR 8886 Rsoil should be in SI unit. From ASHRAE 90.1-2010 SI
    4834           34 :             if (Height <= 0.25) {
    4835            0 :                 Rsoilequ = 0.12; // m2K/W
    4836           34 :             } else if (Height >= 2.5) {
    4837            2 :                 Rsoilequ = 0.92;
    4838              :             } else { // regression from ASHRAE 90.1-2010 SI TABLE C6.10.1 Effective R-Value of Soil, R2 = 0.9967
    4839           32 :                 Rsoilequ = 0.0607 + 0.3479 * Height;
    4840              :             }
    4841              : 
    4842              :             // effective thermal resistance excludes inside and outside air films
    4843           34 :             Reff = 1.0 / Cfactor + Rsoilequ; // Cfactor does not include air films
    4844              : 
    4845           34 :             Rfic = Reff - Rcon;
    4846           34 :             if (Rfic <= 0) {
    4847            0 :                 ShowSevereError(
    4848              :                     state,
    4849            0 :                     format("{}=\"{}\" has calculated R value <= 0.0, must be > 0.0.", state.dataHeatBalMgr->CurrentModuleObject, ConstructAlphas(1)));
    4850            0 :                 ShowContinueError(state, format("Calculated value=[{:.2R}] Check definition.", Rfic));
    4851            0 :                 ErrorsFound = true;
    4852              :             }
    4853              : 
    4854           34 :             auto *mat = s_mat->materials(thisConstruct.LayerPoint(1));
    4855           34 :             mat->Resistance = mat->NominalR = Rfic;
    4856              : 
    4857              :             // Reff includes the wall itself and soil, but excluding thermal resistance of inside or outside air film
    4858              :             // 1/Reff gets reported as the "U-Factor no Film" in the summary report Envelope Summary | Opaque Exterior
    4859           34 :             state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) = Reff;
    4860              :         }
    4861           21 :     }
    4862              : 
    4863            5 :     void CreateAirBoundaryConstructions(EnergyPlusData &state,
    4864              :                                         int &constrNum,   // Counter for Constructions
    4865              :                                         bool &errorsFound // If errors found in input
    4866              :     )
    4867              :     {
    4868              :         static constexpr std::string_view routineName = "CreateAirBoundaryConstructions";
    4869              : 
    4870            5 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    4871            5 :         cCurrentModuleObject = "Construction:AirBoundary";
    4872            5 :         int numAirBoundaryConstructs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    4873            5 :         if (numAirBoundaryConstructs > 0) {
    4874            5 :             auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
    4875            5 :             if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
    4876              :                 // Cannot imagine how you would have numAirBoundaryConstructs > 0 and yet the instances is empty
    4877              :                 // this would indicate a major problem in the input processor, not a problem here
    4878              :                 // I'll still catch this with errorsFound but I cannot make a unit test for it so excluding the line from coverage
    4879            0 :                 ShowSevereError(state,
    4880              :                                 format("{}: Somehow getNumObjectsFound was > 0 but epJSON.find found 0", cCurrentModuleObject)); // LCOV_EXCL_LINE
    4881              :                 errorsFound = true;                                                                                              // LCOV_EXCL_LINE
    4882              :             }
    4883            5 :             auto &instancesValue = instances.value();
    4884           10 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    4885            5 :                 auto const &fields = instance.value();
    4886            5 :                 std::string const &thisObjectName = instance.key();
    4887              : 
    4888            5 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, thisObjectName};
    4889              : 
    4890            5 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
    4891              : 
    4892           10 :                 if (GlobalNames::VerifyUniqueInterObjectName(
    4893            5 :                         state, state.dataHeatBalMgr->UniqueConstructNames, thisObjectName, cCurrentModuleObject, "Name", errorsFound)) {
    4894            0 :                     continue;
    4895              :                 }
    4896              : 
    4897            5 :                 ++constrNum;
    4898            5 :                 auto &thisConstruct = state.dataConstruction->Construct(constrNum);
    4899              : 
    4900            5 :                 thisConstruct.Name = Util::makeUPPER(thisObjectName);
    4901            5 :                 thisConstruct.TypeIsAirBoundary = true;
    4902            5 :                 thisConstruct.IsUsedCTF = false;
    4903              : 
    4904              :                 // Air Exchange Method
    4905           10 :                 std::string airMethod = "None";
    4906            5 :                 if (auto found = fields.find("air_exchange_method");
    4907            5 :                     found != fields.end()) { // find("x") followed by at("x") is the same lookup twice
    4908            2 :                     airMethod = found.value().get<std::string>();
    4909            5 :                 }
    4910            5 :                 if (Util::SameString(airMethod, "SimpleMixing")) {
    4911            2 :                     thisConstruct.TypeIsAirBoundaryMixing = true;
    4912            4 :                     if (auto found = fields.find("simple_mixing_air_changes_per_hour"); found != fields.end()) {
    4913            2 :                         thisConstruct.AirBoundaryACH = found.value().get<Real64>();
    4914              :                     } else {
    4915            0 :                         if (!state.dataInputProcessing->inputProcessor->getDefaultValue(
    4916            0 :                                 state, cCurrentModuleObject, "simple_mixing_air_changes_per_hour", thisConstruct.AirBoundaryACH)) {
    4917            0 :                             errorsFound = true;
    4918              :                         }
    4919            2 :                     }
    4920              : 
    4921            4 :                     if (auto found = fields.find("simple_mixing_schedule_name"); found != fields.end()) {
    4922            0 :                         std::string schedName = found.value().get<std::string>(); // .get<std::string>() creates and returns a new string, no &
    4923            0 :                         if ((thisConstruct.airBoundaryMixingSched = Sched::GetSchedule(state, Util::makeUPPER(schedName))) == nullptr) {
    4924            0 :                             ShowSevereItemNotFound(state, eoh, "Simple Mixing Schedule Name", schedName);
    4925            0 :                             errorsFound = true;
    4926              :                         }
    4927            0 :                     } else {
    4928            2 :                         thisConstruct.airBoundaryMixingSched =
    4929            2 :                             Sched::GetScheduleAlwaysOn(state); // Not an availability manager, but defaults to constant-1.0
    4930            2 :                     }
    4931              :                 }
    4932           10 :             }
    4933            5 :         }
    4934            5 :     }
    4935              : 
    4936          801 :     void GetScheduledSurfaceGains(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
    4937              :     {
    4938              : 
    4939              :         // SUBROUTINE INFORMATION:
    4940              :         //       AUTHOR         Simon Vidanovic
    4941              :         //       DATE WRITTEN   June 2013
    4942              : 
    4943              :         // PURPOSE OF THIS SUBROUTINE:
    4944              :         // Loads scheduled surface gains for solar incident on interior side of the surfaces and absorbed solar energy in
    4945              :         // window layers
    4946              : 
    4947              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4948              :         static constexpr std::string_view RoutineName("GetScheduledSurfaceGains: ");
    4949              :         static constexpr std::string_view routineName = "GetScheduledSurfaceGains";
    4950              : 
    4951              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4952              :         int NumArgs;
    4953              :         int NumAlpha;
    4954              :         int NumNumeric;
    4955              :         int Loop;
    4956              :         int IOStat;
    4957              :         int SurfNum;
    4958              :         int ConstrNum;
    4959              : 
    4960              :         //-----------------------------------------------------------------------
    4961              :         //                SurfaceProperty:SolarIncidentInside
    4962              :         //-----------------------------------------------------------------------
    4963          801 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    4964          801 :         cCurrentModuleObject = "SurfaceProperty:SolarIncidentInside";
    4965              : 
    4966              :         // Check if IDD definition is correct
    4967          801 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumeric);
    4968          801 :         if (NumAlpha != 4) {
    4969            0 :             ShowSevereError(
    4970              :                 state,
    4971            0 :                 format("{}{}: Object Definition indicates not = 4 Alpha Objects, Number Indicated={}", RoutineName, cCurrentModuleObject, NumAlpha));
    4972            0 :             ErrorsFound = true;
    4973              :         }
    4974              : 
    4975          801 :         state.dataSurface->TotSurfIncSolSSG = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    4976          801 :         if (state.dataSurface->TotSurfIncSolSSG > 0) {
    4977            1 :             if (!allocated(state.dataSurface->SurfIncSolSSG)) {
    4978            1 :                 state.dataSurface->SurfIncSolSSG.allocate(state.dataSurface->TotSurfIncSolSSG);
    4979              :             }
    4980              : 
    4981            7 :             for (Loop = 1; Loop <= state.dataSurface->TotSurfIncSolSSG; ++Loop) {
    4982           12 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    4983              :                                                                          cCurrentModuleObject,
    4984              :                                                                          Loop,
    4985            6 :                                                                          state.dataIPShortCut->cAlphaArgs,
    4986              :                                                                          NumAlpha,
    4987            6 :                                                                          state.dataIPShortCut->rNumericArgs,
    4988              :                                                                          NumNumeric,
    4989              :                                                                          IOStat,
    4990            6 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    4991            6 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    4992            6 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    4993            6 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    4994              : 
    4995            6 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
    4996              : 
    4997            6 :                 state.dataSurface->SurfIncSolSSG(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
    4998              : 
    4999              :                 // Assign surface number
    5000            6 :                 SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface);
    5001            6 :                 if (SurfNum == 0) {
    5002            0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2));
    5003            0 :                     ErrorsFound = true;
    5004              :                 } else {
    5005            6 :                     state.dataSurface->SurfIncSolSSG(Loop).SurfPtr = SurfNum;
    5006            6 :                     if (state.dataSurface->UseRepresentativeSurfaceCalculations) {
    5007            0 :                         int repSurfNum = state.dataSurface->Surface(SurfNum).RepresentativeCalcSurfNum;
    5008            0 :                         if (repSurfNum != SurfNum) {
    5009              :                             // Do not use representative surfaces
    5010              : 
    5011              :                             // remove surface from representative constituent list
    5012            0 :                             auto &vec = state.dataSurface->Surface(repSurfNum).ConstituentSurfaceNums;
    5013            0 :                             vec.erase(std::remove(vec.begin(), vec.end(), SurfNum), vec.end());
    5014              : 
    5015              :                             // reset representative surface number
    5016            0 :                             state.dataSurface->Surface(SurfNum).RepresentativeCalcSurfNum = SurfNum;
    5017              :                         }
    5018              :                     }
    5019              :                 }
    5020              : 
    5021              :                 // Assign construction number
    5022            6 :                 ConstrNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct);
    5023            6 :                 if (ConstrNum == 0) {
    5024            0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3));
    5025            0 :                     ErrorsFound = true;
    5026              :                 } else {
    5027            6 :                     state.dataSurface->SurfIncSolSSG(Loop).ConstrPtr = ConstrNum;
    5028              :                 }
    5029              : 
    5030            6 :                 if ((state.dataSurface->SurfIncSolSSG(Loop).sched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(4))) == nullptr) {
    5031            0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4));
    5032            0 :                     ErrorsFound = true;
    5033              :                 }
    5034              :             }
    5035              :         }
    5036              : 
    5037              :         //-----------------------------------------------------------------------
    5038              :         //                SurfaceProperty:SolarIncidentInside
    5039              :         //-----------------------------------------------------------------------
    5040          801 :         cCurrentModuleObject = "ComplexFenestrationProperty:SolarAbsorbedLayers";
    5041              : 
    5042          801 :         state.dataSurface->TotFenLayAbsSSG = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    5043          801 :         if (state.dataSurface->TotFenLayAbsSSG > 0) {
    5044            1 :             if (!allocated(state.dataSurface->FenLayAbsSSG)) {
    5045            1 :                 state.dataSurface->FenLayAbsSSG.allocate(state.dataSurface->TotFenLayAbsSSG);
    5046              :             }
    5047              : 
    5048            2 :             for (Loop = 1; Loop <= state.dataSurface->TotFenLayAbsSSG; ++Loop) {
    5049            2 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5050              :                                                                          cCurrentModuleObject,
    5051              :                                                                          Loop,
    5052            1 :                                                                          state.dataIPShortCut->cAlphaArgs,
    5053              :                                                                          NumAlpha,
    5054            1 :                                                                          state.dataIPShortCut->rNumericArgs,
    5055              :                                                                          NumNumeric,
    5056              :                                                                          IOStat,
    5057            1 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    5058            1 :                                                                          state.dataIPShortCut->lAlphaFieldBlanks,
    5059            1 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    5060            1 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    5061              : 
    5062            1 :                 ErrorObjectHeader eoh{routineName, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
    5063              : 
    5064            1 :                 state.dataSurface->FenLayAbsSSG(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
    5065              : 
    5066              :                 // Assign surface number
    5067            1 :                 SurfNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface);
    5068            1 :                 if (SurfNum == 0) {
    5069            0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2));
    5070            0 :                     ErrorsFound = true;
    5071              :                 } else {
    5072            1 :                     state.dataSurface->FenLayAbsSSG(Loop).SurfPtr = SurfNum;
    5073              :                 }
    5074              : 
    5075              :                 // Assign construction number
    5076            1 :                 ConstrNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct);
    5077            1 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum); // Why is this before the error check?
    5078            1 :                 if (ConstrNum == 0) {
    5079            0 :                     ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3));
    5080            0 :                     ErrorsFound = true;
    5081              :                 } else {
    5082            1 :                     state.dataSurface->FenLayAbsSSG(Loop).ConstrPtr = ConstrNum;
    5083            1 :                     int NumOfScheduledLayers = NumAlpha - 3;
    5084            1 :                     bool NumOfLayersMatch = false;
    5085              :                     // Check if number of layers in construction matches number of layers in schedule surface gains object
    5086            1 :                     if (NumOfScheduledLayers == thisConstruct.TotSolidLayers) {
    5087            1 :                         NumOfLayersMatch = true;
    5088              :                     }
    5089              : 
    5090            1 :                     if (!NumOfLayersMatch) {
    5091            0 :                         ShowSevereError(
    5092              :                             state,
    5093            0 :                             format("{}{}=\"{}, object. Number of scheduled surface gains for each layer does not match number of layers in "
    5094              :                                    "referenced construction.",
    5095              :                                    RoutineName,
    5096              :                                    cCurrentModuleObject,
    5097            0 :                                    state.dataIPShortCut->cAlphaArgs(1)));
    5098            0 :                         ShowContinueError(state,
    5099            0 :                                           format("{} have {} schedule layers and {} have {} layers.",
    5100            0 :                                                  state.dataIPShortCut->cAlphaArgs(1),
    5101              :                                                  NumOfScheduledLayers,
    5102            0 :                                                  state.dataIPShortCut->cAlphaArgs(3),
    5103            0 :                                                  thisConstruct.TotSolidLayers));
    5104            0 :                         ErrorsFound = true;
    5105              :                     }
    5106              : 
    5107            1 :                     if (!allocated(state.dataSurface->FenLayAbsSSG(Loop).scheds)) {
    5108            1 :                         state.dataSurface->FenLayAbsSSG(Loop).scheds.allocate(NumOfScheduledLayers);
    5109              :                     }
    5110              : 
    5111            1 :                     state.dataSurface->FenLayAbsSSG(Loop).NumOfSched = NumOfScheduledLayers;
    5112              : 
    5113            4 :                     for (int i = 1; i <= NumOfScheduledLayers; ++i) {
    5114            3 :                         if ((state.dataSurface->FenLayAbsSSG(Loop).scheds(i) = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(i + 3))) ==
    5115              :                             nullptr) {
    5116            0 :                             ShowSevereItemNotFound(state,
    5117              :                                                    eoh,
    5118            0 :                                                    state.dataIPShortCut->cAlphaFieldNames(NumOfScheduledLayers + 3),
    5119            0 :                                                    state.dataIPShortCut->cAlphaArgs(NumOfScheduledLayers + 3));
    5120            0 :                             ErrorsFound = true;
    5121              :                         }
    5122              :                     }
    5123              :                 }
    5124              :             }
    5125              :         }
    5126              : 
    5127              :         // Check if scheduled surface gains are assigined to each surface in every zone.  If not then warning message to user will be
    5128              :         // issued
    5129          801 :         if ((state.dataSurface->TotSurfIncSolSSG > 0) || (state.dataSurface->TotFenLayAbsSSG > 0)) {
    5130            2 :             for (int iZone = 1; iZone <= state.dataGlobal->NumOfZones; ++iZone) {
    5131            1 :                 CheckScheduledSurfaceGains(state, iZone);
    5132              :             }
    5133              :         }
    5134          801 :     }
    5135              : 
    5136            1 :     void CheckScheduledSurfaceGains(EnergyPlusData &state, int const ZoneNum) // Zone number for which error check will be performed
    5137              :     {
    5138              : 
    5139              :         // SUBROUTINE INFORMATION:
    5140              :         //       AUTHOR         Simon Vidanovic
    5141              :         //       DATE WRITTEN   July 2013
    5142              : 
    5143              :         // PURPOSE OF THIS SUBROUTINE:
    5144              :         // Check if all surfaces within zone are scheduled with surface gains. If not all surfaces within zone are scheduled,
    5145              :         // warning message will be issued and program will continue to execute.
    5146              : 
    5147              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5148              :         int SchedPtr; // scheduled surface gains pointer
    5149              : 
    5150            1 :         bool ZoneUnscheduled = false; // true if all surfaces in the zone are unscheduled
    5151            1 :         bool ZoneScheduled = false;   // true if all surfaces in the zone are scheduled
    5152              : 
    5153            1 :         bool firstZoneSurface = true;
    5154            2 :         for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    5155            1 :             auto const &thisSpace = state.dataHeatBal->space(spaceNum);
    5156            8 :             for (int iSurf = thisSpace.HTSurfaceFirst; iSurf <= thisSpace.HTSurfaceLast; ++iSurf) {
    5157            7 :                 int iConst = state.dataSurface->Surface(iSurf).Construction;
    5158            7 :                 if (state.dataSurface->Surface(iSurf).Class == DataSurfaces::SurfaceClass::Window) {
    5159            1 :                     SchedPtr = SolarShading::WindowScheduledSolarAbs(state, iSurf, iConst);
    5160              :                 } else {
    5161            6 :                     SchedPtr = SolarShading::SurfaceScheduledSolarInc(state, iSurf, iConst);
    5162              :                 }
    5163            7 :                 if (firstZoneSurface) {
    5164            1 :                     if (SchedPtr != 0) {
    5165            1 :                         ZoneScheduled = true;
    5166            1 :                         ZoneUnscheduled = false;
    5167              :                     } else {
    5168            0 :                         ZoneScheduled = false;
    5169            0 :                         ZoneUnscheduled = true;
    5170              :                     }
    5171            1 :                     firstZoneSurface = false;
    5172              :                 } else {
    5173            6 :                     if (SchedPtr != 0) {
    5174            6 :                         ZoneUnscheduled = false;
    5175              :                     } else {
    5176            0 :                         ZoneScheduled = false;
    5177              :                     }
    5178              :                 }
    5179              :             }
    5180            1 :         }
    5181            1 :         if ((!ZoneScheduled) && (!ZoneUnscheduled)) {
    5182              :             // zone is not scheduled nor unscheduled
    5183            0 :             ShowWarningError(state,
    5184            0 :                              format("Zone {} does not have all surfaces scheduled with surface gains.", state.dataHeatBal->Zone(ZoneNum).Name));
    5185            0 :             ShowContinueError(state,
    5186              :                               "If at least one surface in the zone is scheduled with surface gains, then all other surfaces within the same zone "
    5187              :                               "should be scheduled as well.");
    5188            0 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    5189            0 :                 auto const &thisSpace = state.dataHeatBal->space(spaceNum);
    5190            0 :                 for (int iSurf = thisSpace.HTSurfaceFirst; iSurf <= thisSpace.HTSurfaceLast; ++iSurf) {
    5191            0 :                     int iConst = state.dataSurface->Surface(iSurf).Construction;
    5192            0 :                     if (state.dataSurface->Surface(iSurf).Class == DataSurfaces::SurfaceClass::Window) {
    5193            0 :                         SchedPtr = SolarShading::WindowScheduledSolarAbs(state, iSurf, iConst);
    5194              :                     } else {
    5195            0 :                         SchedPtr = SolarShading::SurfaceScheduledSolarInc(state, iSurf, iConst);
    5196              :                     }
    5197              : 
    5198            0 :                     if (SchedPtr == 0) {
    5199            0 :                         ShowContinueError(state, format("Surface {} does not have scheduled surface gains.", state.dataSurface->Surface(iSurf).Name));
    5200              :                     }
    5201              :                 }
    5202            0 :             }
    5203              :         }
    5204            1 :     }
    5205              : 
    5206          801 :     void CreateTCConstructions(EnergyPlusData &state, [[maybe_unused]] bool &ErrorsFound) // If errors found in input
    5207              :     {
    5208              : 
    5209              :         // SUBROUTINE INFORMATION:
    5210              :         //       AUTHOR         Tianzhen Hong
    5211              :         //       DATE WRITTEN   January 2009
    5212              : 
    5213              :         // PURPOSE OF THIS SUBROUTINE:
    5214              :         // This subroutine goes through each TC master construction and creates a complete series
    5215              :         // of the slave thermochromic constructions.
    5216              :         // This subroutine only gets called once in the GetHeatBalanceInput subroutine
    5217              :         //  after materials, constructions and building geometry data are read.
    5218          801 :         auto &s_mat = state.dataMaterial;
    5219              : 
    5220          801 :         int NumNewConst = 0;
    5221         6887 :         for (int Loop = 1; Loop <= state.dataHeatBal->TotConstructs; ++Loop) {
    5222         6086 :             auto &constr = state.dataConstruction->Construct(Loop);
    5223              : 
    5224         6086 :             if (!constr.isTCMaster) {
    5225         6085 :                 continue;
    5226              :             }
    5227              : 
    5228            1 :             auto const *matGlassTC = dynamic_cast<Material::MaterialGlassTC const *>(s_mat->materials(constr.TCMasterMatNum));
    5229            1 :             assert(matGlassTC != nullptr);
    5230            1 :             NumNewConst += matGlassTC->numMatRefs;
    5231              :         }
    5232              : 
    5233          801 :         if (NumNewConst == 0) {
    5234          800 :             return; // no need to go further
    5235              :         }
    5236              : 
    5237              :         // Increase Construct() and copy the extra constructions
    5238            1 :         state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs + NumNewConst);
    5239            1 :         state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs + NumNewConst);
    5240            1 :         state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs + NumNewConst);
    5241            1 :         state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs + NumNewConst);
    5242            1 :         state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs + NumNewConst) = 1.0;
    5243              : 
    5244            1 :         NumNewConst = state.dataHeatBal->TotConstructs;
    5245           14 :         for (int Loop = 1; Loop <= state.dataHeatBal->TotConstructs; ++Loop) {
    5246           13 :             auto &constr = state.dataConstruction->Construct(Loop);
    5247           13 :             if (!constr.isTCMaster) {
    5248           12 :                 continue;
    5249              :             }
    5250              : 
    5251            1 :             auto const *matGlassTC = dynamic_cast<Material::MaterialGlassTC *>(s_mat->materials(constr.TCMasterMatNum));
    5252            1 :             assert(matGlassTC != nullptr);
    5253              : 
    5254            1 :             constr.numTCChildConstrs = matGlassTC->numMatRefs;
    5255            1 :             constr.TCChildConstrs.allocate(constr.numTCChildConstrs);
    5256              : 
    5257              :             // The master thermochromic construction uses the first (i.e., lowest temp) glazing
    5258            1 :             constr.LayerPoint(constr.TCLayerNum) = matGlassTC->matRefs(1).matNum;
    5259            1 :             constr.specTemp = matGlassTC->matRefs(1).specTemp;
    5260              : 
    5261           20 :             for (int iTC = 1; iTC <= constr.numTCChildConstrs; ++iTC) {
    5262           19 :                 ++NumNewConst;
    5263           19 :                 auto &constrNew = state.dataConstruction->Construct(NumNewConst);
    5264              : 
    5265           19 :                 constrNew = constr; // This should be a deep copy
    5266           19 :                 constrNew.Name = format("{}_TC_{:.0R}", constr.Name, matGlassTC->matRefs(iTC).specTemp);
    5267           19 :                 constrNew.LayerPoint(constrNew.TCLayerNum) = matGlassTC->matRefs(iTC).matNum;
    5268           19 :                 constrNew.specTemp = matGlassTC->matRefs(iTC).specTemp;
    5269              : 
    5270           19 :                 constrNew.isTCWindow = true;
    5271           19 :                 constrNew.isTCMaster = false;
    5272           19 :                 constrNew.TCMasterConstrNum = Loop;
    5273              : 
    5274           19 :                 constr.TCChildConstrs(iTC).specTemp = matGlassTC->matRefs(iTC).specTemp;
    5275           19 :                 constr.TCChildConstrs(iTC).constrNum = NumNewConst;
    5276              :             }
    5277              :         }
    5278            1 :         state.dataHeatBal->TotConstructs = NumNewConst;
    5279              :     }
    5280              : 
    5281           10 :     void SetupComplexFenestrationStateInput(EnergyPlusData &state,
    5282              :                                             int &ConstrNum, // num of construction items thus far
    5283              :                                             bool &ErrorsFound)
    5284              :     {
    5285              : 
    5286              :         // SUBROUTINE INFORMATION:
    5287              :         //       AUTHOR         B. Griffith
    5288              :         //       DATE WRITTEN   June 2010
    5289              :         //       MODIFIED       January 2012 (Simon Vidanovic)
    5290              :         //       MODIFIED       May 2012 (Simon Vidanovic)
    5291              : 
    5292              :         // PURPOSE OF THIS SUBROUTINE:
    5293              :         // get input for complex fenestration construction
    5294              : 
    5295              :         // METHODOLOGY EMPLOYED:
    5296              :         // usual GetInput processing.  Matrix input from MatrixDataManager
    5297              : 
    5298              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5299              :         static constexpr std::string_view routineName = "SetupComlexFenestrationStateInput";
    5300              : 
    5301              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5302              :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
    5303              :         int NumNumbers; // Number of Numbers for each GetObjectItem call
    5304              :         int TotalArgs;  // Number of fields for each GetObjectItem call
    5305              :         int IOStatus;   // Used in GetObjectItem
    5306              :         int NumRows;    // temporary size of matrix
    5307              :         int NumCols;    // temporary size of matrix
    5308              :         int NBasis;     // temporary number of elements in basis
    5309              :         int AlphaIndex;
    5310              :         int NumOfTotalLayers;    // total number of layers in the construction
    5311              :         int NumOfOpticalLayers;  // number of optical layers in the construction (excluding gasses and gas mixtures)
    5312              :         int currentOpticalLayer; // current optical layer number.  This is important since optical structures should
    5313              :         // be loaded only with optical layers
    5314              : 
    5315              :         // When reading Construction:ComplexFenestrationState, there is a call of GetMatrix2D which also uses same
    5316              :         // variables from DataIPShortCuts.  Since this can cause some errors in reading, it is important
    5317              :         // to declare local variables for reading Construction:ComplexFenestrationState object(s)
    5318           10 :         Array1D_string locAlphaFieldNames;
    5319           10 :         Array1D_string locNumericFieldNames;
    5320           10 :         Array1D_bool locNumericFieldBlanks;
    5321           10 :         Array1D_bool locAlphaFieldBlanks;
    5322           10 :         Array1D_string locAlphaArgs;
    5323           10 :         Array1D<Real64> locNumericArgs;
    5324           10 :         std::string locCurrentModuleObject;
    5325              : 
    5326           10 :         auto &s_ipsc = state.dataIPShortCut;
    5327           10 :         auto &s_mat = state.dataMaterial;
    5328              : 
    5329              :         // Reading WindowThermalModel:Params
    5330           10 :         s_ipsc->cCurrentModuleObject = "WindowThermalModel:Params";
    5331           10 :         state.dataBSDFWindow->TotThermalModels = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    5332           10 :         s_mat->WindowThermalModel.allocate(state.dataBSDFWindow->TotThermalModels);
    5333              : 
    5334           24 :         for (int Loop = 1; Loop <= state.dataBSDFWindow->TotThermalModels; ++Loop) {
    5335           42 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5336           14 :                                                                      s_ipsc->cCurrentModuleObject,
    5337              :                                                                      Loop,
    5338           14 :                                                                      s_ipsc->cAlphaArgs,
    5339              :                                                                      NumAlphas,
    5340           14 :                                                                      s_ipsc->rNumericArgs,
    5341              :                                                                      NumNumbers,
    5342              :                                                                      IOStatus,
    5343           14 :                                                                      s_ipsc->lNumericFieldBlanks,
    5344              :                                                                      _,
    5345           14 :                                                                      s_ipsc->cAlphaFieldNames,
    5346           14 :                                                                      s_ipsc->cNumericFieldNames);
    5347              : 
    5348           14 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    5349              : 
    5350           14 :             auto &windowThermalModel = s_mat->WindowThermalModel(Loop);
    5351           14 :             windowThermalModel.Name = s_ipsc->cAlphaArgs(1);
    5352              : 
    5353           14 :             windowThermalModel.SDScalar = s_ipsc->rNumericArgs(1);
    5354           14 :             if ((s_ipsc->rNumericArgs(1) < 0.0) || (s_ipsc->rNumericArgs(1) > 1.0)) {
    5355            0 :                 ShowSevereCustom(
    5356              :                     state,
    5357              :                     eoh,
    5358            0 :                     format("{} should be >= 0.0 and <= 1.0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(1), s_ipsc->rNumericArgs(1)));
    5359            0 :                 ErrorsFound = true;
    5360              :             }
    5361              : 
    5362           14 :             windowThermalModel.CalculationStandard =
    5363           14 :                 static_cast<TARCOGGassesParams::Stdrd>(getEnumValue(TARCOGGassesParams::stdrdNamesUC, s_ipsc->cAlphaArgs(2)));
    5364           14 :             windowThermalModel.ThermalModel =
    5365           14 :                 static_cast<TARCOGParams::TARCOGThermalModel>(getEnumValue(TARCOGParams::thermalModelNamesUC, s_ipsc->cAlphaArgs(3)));
    5366           14 :             windowThermalModel.DeflectionModel =
    5367           14 :                 static_cast<TARCOGParams::DeflectionCalculation>(getEnumValue(TARCOGParams::deflectionCalculationNamesUC, s_ipsc->cAlphaArgs(4)));
    5368              : 
    5369           14 :             if (windowThermalModel.DeflectionModel == TARCOGParams::DeflectionCalculation::TEMPERATURE) {
    5370            1 :                 windowThermalModel.VacuumPressureLimit = s_ipsc->rNumericArgs(2);
    5371            1 :                 if (s_ipsc->rNumericArgs(2) <= 0.0) {
    5372            0 :                     ErrorsFound = true;
    5373            0 :                     ShowSevereCustom(
    5374            0 :                         state, eoh, format("{} must be > 0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(2), s_ipsc->rNumericArgs(2)));
    5375              :                 }
    5376              : 
    5377            1 :                 windowThermalModel.InitialTemperature = s_ipsc->rNumericArgs(3);
    5378            1 :                 if (s_ipsc->rNumericArgs(3) <= 0.0) {
    5379            0 :                     ErrorsFound = true;
    5380            0 :                     ShowSevereCustom(
    5381            0 :                         state, eoh, format("{} must be > 0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(3), s_ipsc->rNumericArgs(3)));
    5382              :                 }
    5383              : 
    5384            1 :                 windowThermalModel.InitialPressure = s_ipsc->rNumericArgs(4);
    5385            1 :                 if (s_ipsc->rNumericArgs(4) <= 0.0) {
    5386            0 :                     ErrorsFound = true;
    5387            0 :                     ShowSevereCustom(
    5388            0 :                         state, eoh, format("{} must be > 0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(4), s_ipsc->rNumericArgs(4)));
    5389              :                 }
    5390              :             }
    5391              : 
    5392              :         } // DO Loop = 1, TotThermalModels
    5393              : 
    5394              :         // Reading Construction:ComplexFenestrationState
    5395           10 :         locCurrentModuleObject = "Construction:ComplexFenestrationState";
    5396           10 :         state.dataBSDFWindow->TotComplexFenStates = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, locCurrentModuleObject);
    5397              : 
    5398           10 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, locCurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
    5399           10 :         if (!allocated(locAlphaFieldNames)) {
    5400           10 :             locAlphaFieldNames.allocate(NumAlphas);
    5401              :         }
    5402           10 :         if (!allocated(locNumericFieldNames)) {
    5403           10 :             locNumericFieldNames.allocate(NumNumbers);
    5404              :         }
    5405           10 :         if (!allocated(locNumericFieldBlanks)) {
    5406           10 :             locNumericFieldBlanks.allocate(NumNumbers);
    5407              :         }
    5408           10 :         if (!allocated(locAlphaFieldBlanks)) {
    5409           10 :             locAlphaFieldBlanks.allocate(NumAlphas);
    5410              :         }
    5411           10 :         if (!allocated(locAlphaArgs)) {
    5412           10 :             locAlphaArgs.allocate(NumAlphas);
    5413              :         }
    5414           10 :         if (!allocated(locNumericArgs)) {
    5415           10 :             locNumericArgs.allocate(NumNumbers);
    5416              :         }
    5417              : 
    5418           10 :         state.dataBSDFWindow->FirstBSDF = ConstrNum + 1; // Location of first BSDF construction input (They will be consecutive)
    5419           24 :         for (int Loop = 1; Loop <= state.dataBSDFWindow->TotComplexFenStates; ++Loop) {
    5420           14 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    5421              :                                                                      locCurrentModuleObject,
    5422              :                                                                      Loop,
    5423              :                                                                      locAlphaArgs,
    5424              :                                                                      NumAlphas,
    5425              :                                                                      locNumericArgs,
    5426              :                                                                      NumNumbers,
    5427              :                                                                      IOStatus,
    5428              :                                                                      locNumericFieldBlanks,
    5429              :                                                                      _,
    5430              :                                                                      locAlphaFieldNames,
    5431              :                                                                      locNumericFieldNames);
    5432              : 
    5433           14 :             ErrorObjectHeader eoh{routineName, locCurrentModuleObject, locAlphaArgs(1)};
    5434              : 
    5435           28 :             if (GlobalNames::VerifyUniqueInterObjectName(state,
    5436           14 :                                                          state.dataHeatBalMgr->UniqueConstructNames,
    5437           14 :                                                          locAlphaArgs(1),
    5438           14 :                                                          state.dataHeatBalMgr->CurrentModuleObject,
    5439           14 :                                                          locAlphaFieldNames(1),
    5440              :                                                          ErrorsFound)) {
    5441            0 :                 continue;
    5442              :             }
    5443           14 :             ++ConstrNum;
    5444           14 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    5445              :             // Simon TODO: This is to be confirmed.  If this is just initial value, then we might want to make better guess
    5446           14 :             state.dataHeatBal->NominalRforNominalUCalculation(ConstrNum) = 0.1;
    5447              :             // Simon TODO: If I do not put this, then it is considered that surface is NOT window
    5448           14 :             thisConstruct.TransDiff = 0.1; // This is a place holder to flag
    5449              :             // the construction as a window until
    5450              :             // the correct value is entered in WindowComplexManager
    5451              : 
    5452              :             // Now override the deraults as appropriate
    5453           14 :             thisConstruct.Name = locAlphaArgs(1);
    5454              : 
    5455              :             //    ALLOCATE(Construct(ConstrNum)%BSDFInput)
    5456              : 
    5457              :             // Construct(ConstrNum)%BSDFInput%ThermalConstruction = ThConstNum
    5458              : 
    5459           14 :             thisConstruct.BSDFInput.BasisType = static_cast<DataBSDFWindow::Basis>(getEnumValue(DataBSDFWindow::basisNamesUC, locAlphaArgs(2)));
    5460           14 :             thisConstruct.BSDFInput.BasisSymmetryType =
    5461           14 :                 static_cast<DataBSDFWindow::BasisSymmetry>(getEnumValue(DataBSDFWindow::basisSymmetryNamesUC, locAlphaArgs(3)));
    5462              : 
    5463              :             // Simon: Assign thermal model number
    5464           14 :             thisConstruct.BSDFInput.ThermalModel = Util::FindItemInList(locAlphaArgs(4), s_mat->WindowThermalModel);
    5465           14 :             if (thisConstruct.BSDFInput.ThermalModel == 0) {
    5466            0 :                 ShowSevereItemNotFound(state, eoh, locAlphaFieldNames(4), locAlphaArgs(4));
    5467              :             }
    5468              : 
    5469              :             // ***************************************************************************************
    5470              :             // Basis matrix
    5471              :             // ***************************************************************************************
    5472           14 :             thisConstruct.BSDFInput.BasisMatIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(5));
    5473           14 :             MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.BasisMatIndex, NumRows, NumCols);
    5474           14 :             thisConstruct.BSDFInput.BasisMatNrows = NumRows;
    5475           14 :             thisConstruct.BSDFInput.BasisMatNcols = NumCols;
    5476              : 
    5477           14 :             if (NumCols != 2 && NumCols != 1) {
    5478            0 :                 ErrorsFound = true;
    5479            0 :                 ShowSevereCustom(state,
    5480              :                                  eoh,
    5481            0 :                                  format("{} entered value=\"{}\" invalid matrix dimensions.  Basis matrix dimension can only be 2 x 1.",
    5482              :                                         locAlphaFieldNames(5),
    5483              :                                         locAlphaArgs(5)));
    5484              :             }
    5485           14 :             thisConstruct.BSDFInput.BasisMat.allocate(NumCols, NumRows);
    5486           14 :             MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.BasisMatIndex, thisConstruct.BSDFInput.BasisMat);
    5487           14 :             if (thisConstruct.BSDFInput.BasisType == DataBSDFWindow::Basis::WINDOW) {
    5488           14 :                 WindowComplexManager::CalculateBasisLength(state, thisConstruct.BSDFInput, ConstrNum, thisConstruct.BSDFInput.NBasis);
    5489              :             }
    5490              : 
    5491              :             // determine number of layers and optical layers
    5492           14 :             NumOfTotalLayers = (NumAlphas - 9) / 3;
    5493           14 :             thisConstruct.TotLayers = NumOfTotalLayers;
    5494              : 
    5495           14 :             NumOfOpticalLayers = NumOfTotalLayers / 2 + 1;
    5496              : 
    5497           14 :             thisConstruct.BSDFInput.NumLayers = NumOfOpticalLayers;
    5498           14 :             thisConstruct.BSDFInput.Layer.allocate(NumOfOpticalLayers);
    5499              : 
    5500              :             // check for incomplete field set
    5501           14 :             if (mod((NumAlphas - 9), 3) != 0) {
    5502              :                 // throw warning if incomplete field set
    5503            0 :                 ErrorsFound = true;
    5504            0 :                 ShowSevereCustom(state, eoh, format("{} is missing some of the layers or/and gaps.", locAlphaArgs(1)));
    5505              :             }
    5506              : 
    5507           14 :             if (thisConstruct.BSDFInput.BasisSymmetryType == DataBSDFWindow::BasisSymmetry::None) {
    5508              :                 // Non-Symmetric basis
    5509              : 
    5510           14 :                 NBasis = thisConstruct.BSDFInput.NBasis;
    5511              : 
    5512              :                 // *******************************************************************************
    5513              :                 // Solar front transmittance
    5514              :                 // *******************************************************************************
    5515           14 :                 thisConstruct.BSDFInput.SolFrtTransIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(6));
    5516           14 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.SolFrtTransIndex, NumRows, NumCols);
    5517           14 :                 thisConstruct.BSDFInput.SolFrtTransNrows = NumRows;
    5518           14 :                 thisConstruct.BSDFInput.SolFrtTransNcols = NumCols;
    5519              : 
    5520           14 :                 if (NumRows != NBasis) {
    5521            0 :                     ErrorsFound = true;
    5522            0 :                     ShowSevereCustom(
    5523              :                         state,
    5524              :                         eoh,
    5525            0 :                         format("Solar front transmittance matrix \"{}\" is not the same size as it is defined by basis definition. Basis "
    5526              :                                "size is defined by Matrix:TwoDimension = \"{}\".",
    5527              :                                locAlphaArgs(6),
    5528              :                                locAlphaArgs(5)));
    5529              :                 }
    5530              : 
    5531           14 :                 if (NumRows != NumCols) {
    5532            0 :                     ErrorsFound = true;
    5533            0 :                     ShowSevereCustom(
    5534              :                         state,
    5535              :                         eoh,
    5536            0 :                         format("Solar front transmittance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(6)));
    5537              :                 }
    5538              : 
    5539           14 :                 if (thisConstruct.BSDFInput.BasisType == DataBSDFWindow::Basis::Custom) {
    5540            0 :                     thisConstruct.BSDFInput.NBasis = NumRows; // For custom basis, no rows in transmittance
    5541              :                                                               // matrix defines the basis length
    5542              :                 }
    5543              : 
    5544           14 :                 thisConstruct.BSDFInput.SolFrtTrans.allocate(NumCols, NumRows);
    5545           14 :                 if (thisConstruct.BSDFInput.SolFrtTransIndex == 0) {
    5546            0 :                     ErrorsFound = true;
    5547            0 :                     ShowSevereCustom(
    5548              :                         state,
    5549              :                         eoh,
    5550            0 :                         format("Solar front transmittance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(6)));
    5551              :                 } else {
    5552           14 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.SolFrtTransIndex, thisConstruct.BSDFInput.SolFrtTrans);
    5553              :                 }
    5554              : 
    5555              :                 // *******************************************************************************
    5556              :                 // Solar back reflectance
    5557              :                 // *******************************************************************************
    5558           14 :                 thisConstruct.BSDFInput.SolBkReflIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(7));
    5559           14 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.SolBkReflIndex, NumRows, NumCols);
    5560           14 :                 thisConstruct.BSDFInput.SolBkReflNrows = NumRows;
    5561           14 :                 thisConstruct.BSDFInput.SolBkReflNcols = NumCols;
    5562              : 
    5563           14 :                 if (NumRows != NBasis) {
    5564            0 :                     ErrorsFound = true;
    5565            0 :                     ShowSevereCustom(
    5566              :                         state,
    5567              :                         eoh,
    5568            0 :                         format("Solar back reflectance matrix \"{}\" is not the same size as it is defined by basis definition. Basis size "
    5569              :                                "is defined by Matrix:TwoDimension = \"{}\".",
    5570              :                                locAlphaArgs(7),
    5571              :                                locAlphaArgs(5)));
    5572              :                 }
    5573              : 
    5574           14 :                 if (NumRows != NumCols) {
    5575            0 :                     ErrorsFound = true;
    5576            0 :                     ShowSevereCustom(
    5577            0 :                         state, eoh, format("Solar back reflectance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(7)));
    5578              :                 }
    5579              : 
    5580           14 :                 thisConstruct.BSDFInput.SolBkRefl.allocate(NumCols, NumRows);
    5581           14 :                 if (thisConstruct.BSDFInput.SolBkReflIndex == 0) {
    5582            0 :                     ErrorsFound = true;
    5583            0 :                     ShowSevereCustom(
    5584            0 :                         state, eoh, format("Solar back reflectance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(7)));
    5585              :                 } else {
    5586           14 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.SolBkReflIndex, thisConstruct.BSDFInput.SolBkRefl);
    5587              :                 }
    5588              : 
    5589              :                 // *******************************************************************************
    5590              :                 // Visible front transmittance
    5591              :                 // *******************************************************************************
    5592           14 :                 thisConstruct.BSDFInput.VisFrtTransIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(8));
    5593           14 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.VisFrtTransIndex, NumRows, NumCols);
    5594           14 :                 thisConstruct.BSDFInput.VisFrtTransNrows = NumRows;
    5595           14 :                 thisConstruct.BSDFInput.VisFrtTransNcols = NumCols;
    5596              : 
    5597           14 :                 if (NumRows != NBasis) {
    5598            0 :                     ErrorsFound = true;
    5599            0 :                     ShowSevereCustom(
    5600              :                         state,
    5601              :                         eoh,
    5602            0 :                         format("Visible front transmittance matrix \"{}\" is not the same size as it is defined by basis definition. Basis "
    5603              :                                "size is defined by Matrix:TwoDimension = \"{}\".",
    5604              :                                locAlphaArgs(8),
    5605              :                                locAlphaArgs(5)));
    5606              :                 }
    5607              : 
    5608           14 :                 if (NumRows != NumCols) {
    5609            0 :                     ErrorsFound = true;
    5610            0 :                     ShowSevereCustom(
    5611              :                         state,
    5612              :                         eoh,
    5613            0 :                         format("Visible front transmittance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(8)));
    5614              :                 }
    5615              : 
    5616           14 :                 thisConstruct.BSDFInput.VisFrtTrans.allocate(NumCols, NumRows);
    5617           14 :                 if (thisConstruct.BSDFInput.VisFrtTransIndex == 0) {
    5618            0 :                     ErrorsFound = true;
    5619            0 :                     ShowSevereCustom(
    5620              :                         state,
    5621              :                         eoh,
    5622            0 :                         format("Visible front transmittance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(8)));
    5623              :                 } else {
    5624           14 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.VisFrtTransIndex, thisConstruct.BSDFInput.VisFrtTrans);
    5625              :                 }
    5626              : 
    5627              :                 // *******************************************************************************
    5628              :                 // Visible back reflectance
    5629              :                 // *******************************************************************************
    5630           14 :                 thisConstruct.BSDFInput.VisBkReflIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(9));
    5631           14 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.VisBkReflIndex, NumRows, NumCols);
    5632           14 :                 thisConstruct.BSDFInput.VisBkReflNrows = NumRows;
    5633           14 :                 thisConstruct.BSDFInput.VisBkReflNcols = NumCols;
    5634              : 
    5635           14 :                 if (NumRows != NBasis) {
    5636            0 :                     ErrorsFound = true;
    5637            0 :                     ShowSevereCustom(state,
    5638              :                                      eoh,
    5639            0 :                                      format("Visible back reflectance matrix \"{}\" is not the same size as it is defined by basis definition. Basis "
    5640              :                                             "size is defined by Matrix:TwoDimension = \"{}\".",
    5641              :                                             locAlphaArgs(9),
    5642              :                                             locAlphaArgs(5)));
    5643              :                 }
    5644              : 
    5645           14 :                 if (NumRows != NumCols) {
    5646            0 :                     ErrorsFound = true;
    5647            0 :                     ShowSevereCustom(
    5648            0 :                         state, eoh, format("Visible back reflectance \"{}\" must have the same number of rows and columns.", locAlphaArgs(9)));
    5649              :                 }
    5650              : 
    5651           14 :                 thisConstruct.BSDFInput.VisBkRefl.allocate(NumCols, NumRows);
    5652           14 :                 if (thisConstruct.BSDFInput.VisBkReflIndex == 0) {
    5653            0 :                     ErrorsFound = true;
    5654            0 :                     ShowSevereCustom(
    5655            0 :                         state, eoh, format("Visble back reflectance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(9)));
    5656              :                 } else {
    5657           14 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.VisBkReflIndex, thisConstruct.BSDFInput.VisBkRefl);
    5658              :                 }
    5659              : 
    5660              :                 // ALLOCATE(Construct(ConstrNum)%BSDFInput%Layer(NumOfOpticalLayers))
    5661           76 :                 for (int Layer = 1; Layer <= thisConstruct.TotLayers; ++Layer) {
    5662           62 :                     AlphaIndex = 9 + (Layer * 3) - 2;
    5663           62 :                     currentOpticalLayer = int(Layer / 2) + 1;
    5664              :                     // Material info is contained in the thermal construct
    5665           62 :                     thisConstruct.LayerPoint(Layer) = Material::GetMaterialNum(state, locAlphaArgs(AlphaIndex));
    5666              : 
    5667              :                     // Simon: Load only if optical layer
    5668           62 :                     if (mod(Layer, 2) != 0) {
    5669           38 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).MaterialIndex = thisConstruct.LayerPoint(Layer);
    5670              : 
    5671           38 :                         ++AlphaIndex;
    5672              :                         // *******************************************************************************
    5673              :                         // Front absorptance matrix
    5674              :                         // *******************************************************************************
    5675           76 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex =
    5676           38 :                             MatrixDataManager::MatrixIndex(state, locAlphaArgs(AlphaIndex));
    5677           38 :                         MatrixDataManager::Get2DMatrixDimensions(
    5678           38 :                             state, thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex, NumRows, NumCols);
    5679              : 
    5680           38 :                         if (NumRows != 1) {
    5681            0 :                             ErrorsFound = true;
    5682            0 :                             ShowSevereCustom(state,
    5683              :                                              eoh,
    5684            0 :                                              format("Front absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have only one row.",
    5685              :                                                     locAlphaArgs(AlphaIndex),
    5686              :                                                     currentOpticalLayer));
    5687              :                         }
    5688              : 
    5689           38 :                         if (NumCols != NBasis) {
    5690            0 :                             ErrorsFound = true;
    5691            0 :                             ShowSevereCustom(state,
    5692              :                                              eoh,
    5693            0 :                                              format("Front absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have same number of columns "
    5694              :                                                     "as it is defined by basis matrix."
    5695              :                                                     "Matrix has {} number of columns, while basis definition specifies {} number of columns.",
    5696              :                                                     locAlphaArgs(AlphaIndex),
    5697              :                                                     currentOpticalLayer,
    5698              :                                                     NumCols,
    5699              :                                                     NBasis));
    5700              :                         }
    5701              : 
    5702           38 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).AbsNcols = NumCols;
    5703           38 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbs.allocate(NumCols, NumRows);
    5704           38 :                         if (thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex == 0) {
    5705            0 :                             ErrorsFound = true;
    5706            0 :                             ShowSevereCustom(state,
    5707              :                                              eoh,
    5708            0 :                                              format("Front absorbtance Matrix:TwoDimension = \"{}\" for layer {} is missing from the input file.",
    5709              :                                                     locAlphaArgs(AlphaIndex),
    5710              :                                                     currentOpticalLayer));
    5711              :                         } else {
    5712           38 :                             MatrixDataManager::Get2DMatrix(state,
    5713           38 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex,
    5714           38 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbs);
    5715              :                         }
    5716              : 
    5717           38 :                         ++AlphaIndex;
    5718              :                         // *******************************************************************************
    5719              :                         // Back absorptance matrix
    5720              :                         // *******************************************************************************
    5721           76 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex =
    5722           38 :                             MatrixDataManager::MatrixIndex(state, locAlphaArgs(AlphaIndex));
    5723           38 :                         MatrixDataManager::Get2DMatrixDimensions(
    5724           38 :                             state, thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex, NumRows, NumCols);
    5725              : 
    5726           38 :                         if (NumRows != 1) {
    5727            0 :                             ErrorsFound = true;
    5728            0 :                             ShowSevereCustom(state,
    5729              :                                              eoh,
    5730            0 :                                              format("Back absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have only one row.",
    5731              :                                                     locAlphaArgs(AlphaIndex),
    5732              :                                                     currentOpticalLayer));
    5733              :                         }
    5734              : 
    5735           38 :                         if (NumCols != NBasis) {
    5736            0 :                             ErrorsFound = true;
    5737            0 :                             ShowSevereCustom(state,
    5738              :                                              eoh,
    5739            0 :                                              format("Back absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have same number of columns as "
    5740              :                                                     "it is defined by basis matrix."
    5741              :                                                     "Matrix has {} number of columns, while basis definition specifies {} number of columns.",
    5742              :                                                     locAlphaArgs(AlphaIndex),
    5743              :                                                     currentOpticalLayer,
    5744              :                                                     NumCols,
    5745              :                                                     NBasis));
    5746              :                         }
    5747              : 
    5748           38 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbs.allocate(NumCols, NumRows);
    5749           38 :                         if (thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex == 0) {
    5750            0 :                             ErrorsFound = true;
    5751            0 :                             ShowSevereCustom(state,
    5752              :                                              eoh,
    5753            0 :                                              format("Back absorbtance Matrix:TwoDimension = \"{}\" for layer {} is missing from the input file.",
    5754              :                                                     locAlphaArgs(AlphaIndex),
    5755              :                                                     currentOpticalLayer));
    5756              :                         } else {
    5757           38 :                             MatrixDataManager::Get2DMatrix(state,
    5758           38 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex,
    5759           38 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbs);
    5760              :                         }
    5761              :                     } // if (Mod(Layer, 2) <> 0) then
    5762              :                 }
    5763              :             } else {
    5764              :                 // Axisymmetric basis
    5765            0 :                 NBasis = thisConstruct.BSDFInput.NBasis; // Basis length has already been calculated
    5766            0 :                 state.dataBSDFWindow->BSDFTempMtrx.allocate(NBasis, 1);
    5767              : 
    5768              :                 // *******************************************************************************
    5769              :                 // Solar front transmittance
    5770              :                 // *******************************************************************************
    5771            0 :                 thisConstruct.BSDFInput.SolFrtTransIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(6));
    5772            0 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.SolFrtTransIndex, NumRows, NumCols);
    5773            0 :                 thisConstruct.BSDFInput.SolFrtTransNrows = NBasis;
    5774            0 :                 thisConstruct.BSDFInput.SolFrtTransNcols = NBasis;
    5775              : 
    5776            0 :                 if (NumRows != NBasis) {
    5777            0 :                     ErrorsFound = true;
    5778            0 :                     ShowSevereCustom(
    5779              :                         state,
    5780              :                         eoh,
    5781            0 :                         format("Solar front transmittance matrix \"{}\" is not the same size as it is defined by basis definition. Basis "
    5782              :                                "size is defined by Matrix:TwoDimension = \"{}\".",
    5783              :                                locAlphaArgs(6),
    5784              :                                locAlphaArgs(5)));
    5785              :                 }
    5786              : 
    5787            0 :                 if (NumRows != NumCols) {
    5788            0 :                     ErrorsFound = true;
    5789            0 :                     ShowSevereCustom(
    5790              :                         state,
    5791              :                         eoh,
    5792            0 :                         format("Solar front transmittance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(6)));
    5793              :                 }
    5794              : 
    5795            0 :                 thisConstruct.BSDFInput.SolFrtTrans.allocate(NBasis, NBasis);
    5796            0 :                 if (thisConstruct.BSDFInput.SolFrtTransIndex == 0) {
    5797            0 :                     ErrorsFound = true;
    5798            0 :                     ShowSevereCustom(
    5799              :                         state,
    5800              :                         eoh,
    5801            0 :                         format("Solar front transmittance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(6)));
    5802              :                 } else {
    5803            0 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.SolFrtTransIndex, state.dataBSDFWindow->BSDFTempMtrx);
    5804              : 
    5805            0 :                     thisConstruct.BSDFInput.SolFrtTrans = 0.0;
    5806            0 :                     for (int I = 1; I <= NBasis; ++I) {
    5807            0 :                         thisConstruct.BSDFInput.SolFrtTrans(I, I) = state.dataBSDFWindow->BSDFTempMtrx(I, 1);
    5808              :                     }
    5809              :                 }
    5810              : 
    5811              :                 // *******************************************************************************
    5812              :                 // Solar back reflectance
    5813              :                 // *******************************************************************************
    5814            0 :                 thisConstruct.BSDFInput.SolBkReflIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(7));
    5815            0 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.SolBkReflIndex, NumRows, NumCols);
    5816            0 :                 thisConstruct.BSDFInput.SolBkReflNrows = NBasis;
    5817            0 :                 thisConstruct.BSDFInput.SolBkReflNcols = NBasis;
    5818              : 
    5819            0 :                 if (NumRows != NBasis) {
    5820            0 :                     ErrorsFound = true;
    5821            0 :                     ShowSevereCustom(
    5822              :                         state,
    5823              :                         eoh,
    5824            0 :                         format("Solar back reflectance matrix \"{}\" is not the same size as it is defined by basis definition. Basis size "
    5825              :                                "is defined by Matrix:TwoDimension = \"{}\".",
    5826              :                                locAlphaArgs(7),
    5827              :                                locAlphaArgs(5)));
    5828              :                 }
    5829              : 
    5830            0 :                 if (NumRows != NumCols) {
    5831            0 :                     ErrorsFound = true;
    5832            0 :                     ShowSevereCustom(
    5833            0 :                         state, eoh, format("Solar back reflectance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(7)));
    5834              :                 }
    5835              : 
    5836            0 :                 thisConstruct.BSDFInput.SolBkRefl.allocate(NBasis, NBasis);
    5837            0 :                 if (thisConstruct.BSDFInput.SolBkReflIndex == 0) {
    5838            0 :                     ErrorsFound = true;
    5839            0 :                     ShowSevereCustom(
    5840            0 :                         state, eoh, format("Solar back reflectance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(7)));
    5841              :                 } else {
    5842            0 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.SolBkReflIndex, state.dataBSDFWindow->BSDFTempMtrx);
    5843            0 :                     thisConstruct.BSDFInput.SolBkRefl = 0.0;
    5844            0 :                     for (int I = 1; I <= NBasis; ++I) {
    5845            0 :                         thisConstruct.BSDFInput.SolBkRefl(I, I) = state.dataBSDFWindow->BSDFTempMtrx(I, 1);
    5846              :                     }
    5847              :                 }
    5848              : 
    5849              :                 // *******************************************************************************
    5850              :                 // Visible front transmittance
    5851              :                 // *******************************************************************************
    5852            0 :                 thisConstruct.BSDFInput.VisFrtTransIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(8));
    5853            0 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.VisFrtTransIndex, NumRows, NumCols);
    5854            0 :                 thisConstruct.BSDFInput.VisFrtTransNrows = NBasis;
    5855            0 :                 thisConstruct.BSDFInput.VisFrtTransNcols = NBasis;
    5856              : 
    5857            0 :                 if (NumRows != NBasis) {
    5858            0 :                     ErrorsFound = true;
    5859            0 :                     ShowSevereCustom(
    5860              :                         state,
    5861              :                         eoh,
    5862            0 :                         format("Visible front transmittance matrix \"{}\" is not the same size as it is defined by basis definition. Basis "
    5863              :                                "size is defined by Matrix:TwoDimension = \"{}\".",
    5864              :                                locAlphaArgs(8),
    5865              :                                locAlphaArgs(5)));
    5866              :                 }
    5867              : 
    5868            0 :                 if (NumRows != NumCols) {
    5869            0 :                     ErrorsFound = true;
    5870            0 :                     ShowSevereCustom(
    5871              :                         state,
    5872              :                         eoh,
    5873            0 :                         format("Visible front transmittance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(8)));
    5874              :                 }
    5875              : 
    5876            0 :                 thisConstruct.BSDFInput.VisFrtTrans.allocate(NBasis, NBasis);
    5877            0 :                 if (thisConstruct.BSDFInput.VisFrtTransIndex == 0) {
    5878            0 :                     ErrorsFound = true;
    5879            0 :                     ShowSevereCustom(
    5880              :                         state,
    5881              :                         eoh,
    5882            0 :                         format("Visible front transmittance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(8)));
    5883              :                 } else {
    5884            0 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.VisFrtTransIndex, state.dataBSDFWindow->BSDFTempMtrx);
    5885            0 :                     thisConstruct.BSDFInput.VisFrtTrans = 0.0;
    5886            0 :                     for (int I = 1; I <= NBasis; ++I) {
    5887            0 :                         thisConstruct.BSDFInput.VisFrtTrans(I, I) = state.dataBSDFWindow->BSDFTempMtrx(I, 1);
    5888              :                     }
    5889              :                 }
    5890              : 
    5891              :                 // *******************************************************************************
    5892              :                 // Visible back reflectance
    5893              :                 // *******************************************************************************
    5894            0 :                 thisConstruct.BSDFInput.VisBkReflIndex = MatrixDataManager::MatrixIndex(state, locAlphaArgs(9));
    5895            0 :                 MatrixDataManager::Get2DMatrixDimensions(state, thisConstruct.BSDFInput.VisBkReflIndex, NumRows, NumCols);
    5896            0 :                 thisConstruct.BSDFInput.VisBkReflNrows = NBasis;
    5897            0 :                 thisConstruct.BSDFInput.VisBkReflNcols = NBasis;
    5898              : 
    5899            0 :                 if (NumRows != NBasis) {
    5900            0 :                     ErrorsFound = true;
    5901            0 :                     ShowSevereCustom(state,
    5902              :                                      eoh,
    5903            0 :                                      format("Visible back reflectance matrix \"{}\" is not the same size as it is defined by basis definition. Basis "
    5904              :                                             "size is defined by Matrix:TwoDimension = \"{}\".",
    5905              :                                             locAlphaArgs(9),
    5906              :                                             locAlphaArgs(5)));
    5907              :                 }
    5908              : 
    5909            0 :                 if (NumRows != NumCols) {
    5910            0 :                     ErrorsFound = true;
    5911            0 :                     ShowSevereCustom(
    5912            0 :                         state, eoh, format("Visible back reflectance matrix \"{}\" must have the same number of rows and columns.", locAlphaArgs(9)));
    5913              :                 }
    5914              : 
    5915            0 :                 thisConstruct.BSDFInput.VisBkRefl.allocate(NBasis, NBasis);
    5916            0 :                 if (thisConstruct.BSDFInput.VisBkReflIndex == 0) {
    5917            0 :                     ErrorsFound = true;
    5918            0 :                     ShowSevereCustom(
    5919            0 :                         state, eoh, format("Visible back reflectance Matrix:TwoDimension = \"{}\" is missing from the input file.", locAlphaArgs(9)));
    5920              :                 } else {
    5921            0 :                     MatrixDataManager::Get2DMatrix(state, thisConstruct.BSDFInput.VisBkReflIndex, state.dataBSDFWindow->BSDFTempMtrx);
    5922            0 :                     thisConstruct.BSDFInput.VisBkRefl = 0.0;
    5923            0 :                     for (int I = 1; I <= NBasis; ++I) {
    5924            0 :                         thisConstruct.BSDFInput.VisBkRefl(I, I) = state.dataBSDFWindow->BSDFTempMtrx(I, 1);
    5925              :                     }
    5926              :                 }
    5927              : 
    5928              :                 // determine number of layers
    5929              :                 // Construct(ConstrNum)%TotLayers = (NumAlphas - 9)/3
    5930              : 
    5931              :                 // check for incomplete field set
    5932              :                 // IF (Mod((NumAlphas - 9), 3) /= 0) Then
    5933              :                 // throw warning if incomplete field set
    5934              :                 //  CALL ShowWarningError(state, 'Construction:ComplexFenestrationState: Axisymmetric properties have incomplete field &
    5935              :                 //   & set')
    5936              :                 // ENDIF
    5937              : 
    5938              :                 // ALLOCATE(Construct(ConstrNum)%BSDFInput%Layer(NumOfOpticalLayers))
    5939            0 :                 for (int Layer = 1; Layer <= thisConstruct.TotLayers; ++Layer) {
    5940              : 
    5941            0 :                     if (mod(Layer, 2) != 0) {
    5942            0 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).MaterialIndex = thisConstruct.LayerPoint(Layer);
    5943              : 
    5944              :                         // *******************************************************************************
    5945              :                         // Front absorptance matrix
    5946              :                         // *******************************************************************************
    5947            0 :                         ++AlphaIndex;
    5948            0 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex =
    5949            0 :                             MatrixDataManager::MatrixIndex(state, locAlphaArgs(AlphaIndex));
    5950            0 :                         MatrixDataManager::Get2DMatrixDimensions(
    5951            0 :                             state, thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex, NumRows, NumCols);
    5952              : 
    5953            0 :                         if (NumRows != 1) {
    5954            0 :                             ErrorsFound = true;
    5955            0 :                             ShowSevereCustom(state,
    5956              :                                              eoh,
    5957            0 :                                              format("Front absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have only one row.",
    5958              :                                                     locAlphaArgs(AlphaIndex),
    5959              :                                                     currentOpticalLayer));
    5960              :                         }
    5961              : 
    5962            0 :                         if (NumCols != NBasis) {
    5963            0 :                             ErrorsFound = true;
    5964            0 :                             ShowSevereCustom(state,
    5965              :                                              eoh,
    5966            0 :                                              format("Front absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have same number of columns "
    5967              :                                                     "as it is defined by basis matrix."
    5968              :                                                     "Matrix has {} number of columns, while basis definition specifies {} number of columns.",
    5969              :                                                     locAlphaArgs(AlphaIndex),
    5970              :                                                     currentOpticalLayer,
    5971              :                                                     NumCols,
    5972              :                                                     NBasis));
    5973              :                         }
    5974              : 
    5975            0 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).AbsNcols = NumCols;
    5976            0 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbs.allocate(NumCols, NumRows);
    5977              : 
    5978            0 :                         if (thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex == 0) {
    5979            0 :                             ErrorsFound = true;
    5980            0 :                             ShowSevereCustom(state,
    5981              :                                              eoh,
    5982            0 :                                              format("Front absorbtance Matrix:TwoDimension = \"{}\" for layer {} is missing from the input file.",
    5983              :                                                     locAlphaArgs(AlphaIndex),
    5984              :                                                     currentOpticalLayer));
    5985              :                         } else {
    5986            0 :                             MatrixDataManager::Get2DMatrix(state,
    5987            0 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbsIndex,
    5988            0 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).FrtAbs);
    5989              :                         }
    5990              : 
    5991              :                         // *******************************************************************************
    5992              :                         // Back absorptance matrix
    5993              :                         // *******************************************************************************
    5994            0 :                         ++AlphaIndex;
    5995            0 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex =
    5996            0 :                             MatrixDataManager::MatrixIndex(state, locAlphaArgs(AlphaIndex));
    5997            0 :                         MatrixDataManager::Get2DMatrixDimensions(
    5998            0 :                             state, thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex, NumRows, NumCols);
    5999              : 
    6000            0 :                         if (NumRows != 1) {
    6001            0 :                             ErrorsFound = true;
    6002            0 :                             ShowSevereCustom(state,
    6003              :                                              eoh,
    6004            0 :                                              format("Back absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have only one row.",
    6005              :                                                     locAlphaArgs(AlphaIndex),
    6006              :                                                     currentOpticalLayer));
    6007              :                         }
    6008              : 
    6009            0 :                         if (NumCols != NBasis) {
    6010            0 :                             ErrorsFound = true;
    6011            0 :                             ShowSevereCustom(state,
    6012              :                                              eoh,
    6013            0 :                                              format("Back absorbtance Matrix:TwoDimension = \"{}\" for layer {} must have same number of columns as "
    6014              :                                                     "it is defined by basis matrix."
    6015              :                                                     "Matrix has {} number of columns, while basis definition specifies {} number of columns.",
    6016              :                                                     locAlphaArgs(AlphaIndex),
    6017              :                                                     currentOpticalLayer,
    6018              :                                                     NumCols,
    6019              :                                                     NBasis));
    6020              :                         }
    6021              : 
    6022            0 :                         thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbs.allocate(NumCols, NumRows);
    6023              : 
    6024            0 :                         if (thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex == 0) {
    6025            0 :                             ErrorsFound = true;
    6026            0 :                             ShowSevereCustom(state,
    6027              :                                              eoh,
    6028            0 :                                              format("Back absorbtance Matrix:TwoDimension = \"{}\" for layer {} is missing from the input file.",
    6029              :                                                     locAlphaArgs(AlphaIndex),
    6030              :                                                     currentOpticalLayer));
    6031              :                         } else {
    6032            0 :                             MatrixDataManager::Get2DMatrix(state,
    6033            0 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbsIndex,
    6034            0 :                                                            thisConstruct.BSDFInput.Layer(currentOpticalLayer).BkAbs);
    6035              :                         }
    6036              :                     } // if (Mod(Layer, 2) <> 0) then
    6037              :                 }
    6038              : 
    6039            0 :                 state.dataBSDFWindow->BSDFTempMtrx.deallocate();
    6040              :             }
    6041           14 :             thisConstruct.TypeIsWindow = true;
    6042           14 :             thisConstruct.WindowTypeBSDF = true;
    6043              :         }
    6044              : 
    6045              :         // Do not forget to deallocate localy allocated variables
    6046           10 :         if (allocated(locAlphaFieldNames)) {
    6047           10 :             locAlphaFieldNames.deallocate();
    6048              :         }
    6049           10 :         if (allocated(locNumericFieldNames)) {
    6050           10 :             locNumericFieldNames.deallocate();
    6051              :         }
    6052           10 :         if (allocated(locNumericFieldBlanks)) {
    6053           10 :             locNumericFieldBlanks.deallocate();
    6054              :         }
    6055           10 :         if (allocated(locAlphaFieldBlanks)) {
    6056           10 :             locAlphaFieldBlanks.deallocate();
    6057              :         }
    6058           10 :         if (allocated(locAlphaArgs)) {
    6059           10 :             locAlphaArgs.deallocate();
    6060              :         }
    6061           10 :         if (allocated(locNumericArgs)) {
    6062           10 :             locNumericArgs.deallocate();
    6063              :         }
    6064              : 
    6065           10 :         if (ErrorsFound) {
    6066            0 :             ShowFatalError(state, "Error in complex fenestration input.");
    6067              :         }
    6068           10 :     }
    6069              : 
    6070          788 :     void InitConductionTransferFunctions(EnergyPlusData &state)
    6071              :     {
    6072          788 :         bool ErrorsFound(false); // Flag for input error condition
    6073          788 :         bool DoCTFErrorReport(false);
    6074         6838 :         for (auto &construction : state.dataConstruction->Construct) {
    6075         6050 :             construction.calculateTransferFunction(state, ErrorsFound, DoCTFErrorReport);
    6076         6050 :             if (construction.NumHistories > 1) {
    6077           82 :                 state.dataHeatBal->SimpleCTFOnly = false;
    6078              :             }
    6079         6050 :             if (construction.NumCTFTerms > state.dataHeatBal->MaxCTFTerms) {
    6080         1271 :                 state.dataHeatBal->MaxCTFTerms = construction.NumCTFTerms;
    6081              :             }
    6082              :         }
    6083          788 :         if (state.dataHeatBal->AnyInternalHeatSourceInInput) {
    6084           31 :             state.dataHeatBal->SimpleCTFOnly = false;
    6085              :         }
    6086              : 
    6087         6838 :         for (auto &construction : state.dataConstruction->Construct) {
    6088         6050 :             if (!construction.IsUsedCTF) {
    6089         1863 :                 continue;
    6090              :             }
    6091         4187 :             construction.reportLayers(state);
    6092              :         }
    6093              : 
    6094              :         bool InitCTFDoReport;
    6095         2364 :         General::ScanForReports(state, "Constructions", InitCTFDoReport, "Constructions");
    6096          788 :         if (InitCTFDoReport || DoCTFErrorReport) {
    6097          304 :             print(state.files.eio,
    6098              :                   "! <Construction CTF>,Construction Name,Index,#Layers,#CTFs,Time Step {{hours}},ThermalConductance "
    6099              :                   "{{w/m2-K}},OuterThermalAbsorptance,InnerThermalAbsorptance,OuterSolarAbsorptance,InnerSolarAbsorptance,Roughness\n");
    6100          304 :             print(state.files.eio,
    6101              :                   "! <Material CTF Summary>,Material Name,Thickness {{m}},Conductivity {{w/m-K}},Density {{kg/m3}},Specific Heat "
    6102              :                   "{{J/kg-K}},ThermalResistance {{m2-K/w}}\n");
    6103          304 :             print(state.files.eio, "! <Material:Air>,Material Name,ThermalResistance {{m2-K/w}}\n");
    6104          304 :             print(state.files.eio, "! <CTF>,Time,Outside,Cross,Inside,Flux (except final one)\n");
    6105              : 
    6106          304 :             int cCounter = 0; // just used to keep construction index in output report
    6107         3275 :             for (auto &construction : state.dataConstruction->Construct) {
    6108         2971 :                 cCounter++;
    6109         2971 :                 if (!construction.IsUsedCTF) {
    6110         1086 :                     continue;
    6111              :                 }
    6112         1885 :                 construction.reportTransferFunction(state, cCounter);
    6113              :             }
    6114              :         }
    6115              : 
    6116          788 :         if (ErrorsFound) {
    6117            0 :             ShowFatalError(state, "Program terminated for reasons listed (InitConductionTransferFunctions)");
    6118              :         }
    6119          788 :     }
    6120              : 
    6121              : } // namespace HeatBalanceManager
    6122              : 
    6123              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1