LCOV - code coverage report
Current view: top level - EnergyPlus - HeatBalanceManager.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2591 3972 65.2 %
Date: 2024-08-24 18:31:18 Functions: 37 38 97.4 %

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

Generated by: LCOV version 1.14