LCOV - code coverage report
Current view: top level - EnergyPlus - HeatBalanceManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 60.9 % 3202 1949
Test Date: 2025-05-22 16:09:37 Functions: 88.6 % 35 31

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

Generated by: LCOV version 2.0-1