LCOV - code coverage report
Current view: top level - EnergyPlus - DataHeatBalance.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 452 550 82.2 %
Date: 2024-08-24 18:31:18 Functions: 16 16 100.0 %

          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 <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Array.functions.hh>
      53             : #include <ObjexxFCL/Fmath.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/Construction.hh>
      57             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      58             : #include <EnergyPlus/DataEnvironment.hh>
      59             : #include <EnergyPlus/DataHeatBalSurface.hh>
      60             : #include <EnergyPlus/DataHeatBalance.hh>
      61             : #include <EnergyPlus/DataSurfaces.hh>
      62             : #include <EnergyPlus/DaylightingManager.hh>
      63             : #include <EnergyPlus/Material.hh>
      64             : #include <EnergyPlus/OutputProcessor.hh>
      65             : #include <EnergyPlus/UtilityRoutines.hh>
      66             : 
      67             : namespace EnergyPlus::DataHeatBalance {
      68             : 
      69             : // MODULE INFORMATION:
      70             : //       AUTHOR         Rick Strand
      71             : //       DATE WRITTEN   August 1997 (rewritten)
      72             : //       MODIFIED       Aug-Oct 1997 RKS (added derived types)
      73             : //       MODIFIED       Feb 1999 (FW) Added visible radiation parameters,
      74             : //                      WindowShadingControl type and SurfaceWindowCalc type
      75             : //                      Sep 1999 (FW) Added/modified Window4 gas variables
      76             : //                      Jul 2003 (CC) Added reference temperature variable for air models
      77             : //                      Aug 2003 (FW) Added FractionReturnAirPlenTempCoeff1 and
      78             : //                      FractionReturnAirPlenTempCoeff2 to Type LightsData
      79             : //                      Nov 2003 (FW) Add FullExteriorWithRefl and FullInteriorExteriorWithRefl
      80             : //                       as SolarDistribution values
      81             : //                      Dec 2003 (PGE) Added Zone List and Zone Group; added SNLoad variables
      82             : //                      August 2006 (COP) Added variable k coefficient and PCM enthalpy.
      83             : //                      Dec 2006 (DJS-PSU) Added ecoroof material
      84             : //                      Dec 2008 TH added new properties to MaterialProperties and
      85             : //                              ConstructionData for thermochromic windows
      86             : //       RE-ENGINEERED  na
      87             : 
      88             : // PURPOSE OF THIS MODULE:
      89             : // This module should contain the information that is needed to pass
      90             : // from the Heat Balance Module and all of the Zone Initializations
      91             : // such as ConductionTransferFunction, GlassCalculation,
      92             : // SolarShading, etc. Modules.
      93             : 
      94             : // Using/Aliasing
      95             : using namespace DataVectorTypes;
      96             : using DataBSDFWindow::BSDFLayerAbsorpStruct;
      97             : using DataBSDFWindow::BSDFWindowInputStruct;
      98             : 
      99             : // Functions
     100             : 
     101      970159 : Real64 SpaceData::sumHATsurf(EnergyPlusData &state)
     102             : {
     103             :     // PURPOSE OF THIS FUNCTION:
     104             :     // This function calculates the space sum of Hc*Area*Tsurf.
     105             : 
     106      970159 :     Real64 sumHATsurf = 0.0;
     107             : 
     108     8005943 :     for (int surfNum = this->HTSurfaceFirst; surfNum <= this->HTSurfaceLast; ++surfNum) {
     109     7035784 :         Real64 Area = state.dataSurface->Surface(surfNum).Area;
     110             : 
     111     7035784 :         if (state.dataSurface->Surface(surfNum).Class == DataSurfaces::SurfaceClass::Window) {
     112      545959 :             if (state.dataSurface->SurfWinDividerArea(surfNum) > 0.0) {
     113           0 :                 if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(surfNum))) {
     114             :                     // The area is the shade or blind area = sum of the glazing area and the divider area (which is zero if no divider)
     115           0 :                     Area += state.dataSurface->SurfWinDividerArea(surfNum);
     116             :                 } else {
     117             :                     // Window divider contribution (only for window with divider and no interior shade or blind)
     118           0 :                     sumHATsurf += state.dataHeatBalSurf->SurfHConvInt(surfNum) * state.dataSurface->SurfWinDividerArea(surfNum) *
     119           0 :                                   (1.0 + 2.0 * state.dataSurface->SurfWinProjCorrDivIn(surfNum)) * state.dataSurface->SurfWinDividerTempIn(surfNum);
     120             :                 }
     121             :             }
     122             : 
     123      545959 :             if (state.dataSurface->SurfWinFrameArea(surfNum) > 0.0) {
     124             :                 // Window frame contribution
     125           0 :                 sumHATsurf += state.dataHeatBalSurf->SurfHConvInt(surfNum) * state.dataSurface->SurfWinFrameArea(surfNum) *
     126           0 :                               (1.0 + state.dataSurface->SurfWinProjCorrFrIn(surfNum)) * state.dataSurface->SurfWinFrameTempIn(surfNum);
     127             :             }
     128             :         }
     129             : 
     130     7035784 :         sumHATsurf += state.dataHeatBalSurf->SurfHConvInt(surfNum) * Area * state.dataHeatBalSurf->SurfTempInTmp(surfNum);
     131             :     }
     132             : 
     133      970159 :     return sumHATsurf;
     134             : }
     135             : 
     136      970159 : Real64 ZoneData::sumHATsurf(EnergyPlusData &state)
     137             : {
     138      970159 :     Real64 sumHATsurf = 0.0;
     139     1940318 :     for (int spaceNum : this->spaceIndexes) {
     140      970159 :         sumHATsurf += state.dataHeatBal->space(spaceNum).sumHATsurf(state);
     141      970159 :     }
     142      970159 :     return sumHATsurf;
     143             : }
     144    19871224 : void ZoneData::SetOutBulbTempAt(EnergyPlusData &state)
     145             : {
     146             :     // SUBROUTINE INFORMATION:
     147             :     //       AUTHOR         Noel Keen (LBL)/Linda Lawrie
     148             :     //       DATE WRITTEN   August 2010
     149             :     //       MODIFIED       na
     150             :     //       RE-ENGINEERED  na
     151             : 
     152             :     // PURPOSE OF THIS SUBROUTINE:
     153             :     // Routine provides facility for doing bulk Set Temperature at Height.
     154             : 
     155    19871224 :     if (state.dataEnvrn->SiteTempGradient == 0.0) {
     156           0 :         OutDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
     157           0 :         OutWetBulbTemp = state.dataEnvrn->OutWetBulbTemp;
     158             :     } else {
     159             :         // Base temperatures at Z = 0 (C)
     160    19871224 :         Real64 const BaseDryTemp(state.dataEnvrn->OutDryBulbTemp + state.dataEnvrn->WeatherFileTempModCoeff);
     161    19871224 :         Real64 const BaseWetTemp(state.dataEnvrn->OutWetBulbTemp + state.dataEnvrn->WeatherFileTempModCoeff);
     162             : 
     163    19871224 :         Real64 const Z(Centroid.z); // Centroid value
     164    19871224 :         if (Z <= 0.0) {
     165      214705 :             OutDryBulbTemp = BaseDryTemp;
     166      214705 :             OutWetBulbTemp = BaseWetTemp;
     167             :         } else {
     168    19656519 :             OutDryBulbTemp = BaseDryTemp - state.dataEnvrn->SiteTempGradient * DataEnvironment::EarthRadius * Z / (DataEnvironment::EarthRadius + Z);
     169    19656519 :             OutWetBulbTemp = BaseWetTemp - state.dataEnvrn->SiteTempGradient * DataEnvironment::EarthRadius * Z / (DataEnvironment::EarthRadius + Z);
     170             :         }
     171             :     }
     172    19871224 : }
     173             : 
     174    19866168 : void ZoneData::SetWindSpeedAt(EnergyPlusData const &state, Real64 const fac)
     175             : {
     176             :     // SUBROUTINE INFORMATION:
     177             :     //       AUTHOR         Linda Lawrie
     178             :     //       DATE WRITTEN   June 2013
     179             :     //       MODIFIED       na
     180             :     //       RE-ENGINEERED  na
     181             : 
     182             :     // PURPOSE OF THIS SUBROUTINE:
     183             :     // Routine provides facility for doing bulk Set Windspeed at Height.
     184             : 
     185    19866168 :     if (state.dataEnvrn->SiteWindExp == 0.0) {
     186           0 :         WindSpeed = state.dataEnvrn->WindSpeed;
     187             :     } else {
     188    19866168 :         Real64 const Z(Centroid.z); // Centroid value
     189    19866168 :         if (Z <= 0.0) {
     190      214650 :             WindSpeed = 0.0;
     191             :         } else {
     192             :             //  [Met] - at meterological Station, Height of measurement is usually 10m above ground
     193             :             //  LocalWindSpeed = Windspeed [Met] * (Wind Boundary LayerThickness [Met]/Height [Met])**Wind Exponent[Met] &
     194             :             //                     * (Height above ground / Site Wind Boundary Layer Thickness) ** Site Wind Exponent
     195    19651518 :             WindSpeed = fac * std::pow(Z, state.dataEnvrn->SiteWindExp);
     196             :         }
     197             :     }
     198    19866168 : }
     199             : 
     200    19866168 : void ZoneData::SetWindDirAt(Real64 const fac)
     201             : {
     202    19866168 :     WindDir = fac;
     203    19866168 : }
     204             : 
     205        5072 : void AirReportVars::setUpOutputVars(EnergyPlusData &state, std::string_view prefix, std::string const &name)
     206             : {
     207       15216 :     SetupOutputVariable(state,
     208       10144 :                         format("{} Mean Air Temperature", prefix),
     209             :                         Constant::Units::C,
     210        5072 :                         this->MeanAirTemp,
     211             :                         OutputProcessor::TimeStepType::Zone,
     212             :                         OutputProcessor::StoreType::Average,
     213             :                         name);
     214       15216 :     SetupOutputVariable(state,
     215       10144 :                         format("{} Wetbulb Globe Temperature", prefix),
     216             :                         Constant::Units::C,
     217        5072 :                         this->WetbulbGlobeTemp,
     218             :                         OutputProcessor::TimeStepType::Zone,
     219             :                         OutputProcessor::StoreType::Average,
     220             :                         name);
     221       15216 :     SetupOutputVariable(state,
     222       10144 :                         format("{} Operative Temperature", prefix),
     223             :                         Constant::Units::C,
     224        5072 :                         this->OperativeTemp,
     225             :                         OutputProcessor::TimeStepType::Zone,
     226             :                         OutputProcessor::StoreType::Average,
     227             :                         name);
     228       15216 :     SetupOutputVariable(state,
     229       10144 :                         format("{} Mean Air Dewpoint Temperature", prefix),
     230             :                         Constant::Units::C,
     231        5072 :                         this->MeanAirDewPointTemp,
     232             :                         OutputProcessor::TimeStepType::Zone,
     233             :                         OutputProcessor::StoreType::Average,
     234             :                         name);
     235       15216 :     SetupOutputVariable(state,
     236       10144 :                         format("{} Mean Air Humidity Ratio", prefix),
     237             :                         Constant::Units::kgWater_kgDryAir,
     238        5072 :                         this->MeanAirHumRat,
     239             :                         OutputProcessor::TimeStepType::Zone,
     240             :                         OutputProcessor::StoreType::Average,
     241             :                         name);
     242       15216 :     SetupOutputVariable(state,
     243       10144 :                         format("{} Air Heat Balance Internal Convective Heat Gain Rate", prefix),
     244             :                         Constant::Units::W,
     245        5072 :                         this->SumIntGains,
     246             :                         OutputProcessor::TimeStepType::System,
     247             :                         OutputProcessor::StoreType::Average,
     248             :                         name);
     249       15216 :     SetupOutputVariable(state,
     250       10144 :                         format("{} Air Heat Balance Surface Convection Rate", prefix),
     251             :                         Constant::Units::W,
     252        5072 :                         this->SumHADTsurfs,
     253             :                         OutputProcessor::TimeStepType::System,
     254             :                         OutputProcessor::StoreType::Average,
     255             :                         name);
     256       15216 :     SetupOutputVariable(state,
     257       10144 :                         format("{} Air Heat Balance Interzone Air Transfer Rate", prefix),
     258             :                         Constant::Units::W,
     259        5072 :                         this->SumMCpDTzones,
     260             :                         OutputProcessor::TimeStepType::System,
     261             :                         OutputProcessor::StoreType::Average,
     262             :                         name);
     263       15216 :     SetupOutputVariable(state,
     264       10144 :                         format("{} Air Heat Balance Outdoor Air Transfer Rate", prefix),
     265             :                         Constant::Units::W,
     266        5072 :                         this->SumMCpDtInfil,
     267             :                         OutputProcessor::TimeStepType::System,
     268             :                         OutputProcessor::StoreType::Average,
     269             :                         name);
     270       15216 :     SetupOutputVariable(state,
     271       10144 :                         format("{} Air Heat Balance System Air Transfer Rate", prefix),
     272             :                         Constant::Units::W,
     273        5072 :                         this->SumMCpDTsystem,
     274             :                         OutputProcessor::TimeStepType::System,
     275             :                         OutputProcessor::StoreType::Average,
     276             :                         name);
     277       15216 :     SetupOutputVariable(state,
     278       10144 :                         format("{} Air Heat Balance System Convective Heat Gain Rate", prefix),
     279             :                         Constant::Units::W,
     280        5072 :                         this->SumNonAirSystem,
     281             :                         OutputProcessor::TimeStepType::System,
     282             :                         OutputProcessor::StoreType::Average,
     283             :                         name);
     284       15216 :     SetupOutputVariable(state,
     285       10144 :                         format("{} Air Heat Balance Air Energy Storage Rate", prefix),
     286             :                         Constant::Units::W,
     287        5072 :                         this->CzdTdt,
     288             :                         OutputProcessor::TimeStepType::System,
     289             :                         OutputProcessor::StoreType::Average,
     290             :                         name);
     291        5072 :     if (state.dataGlobal->DisplayAdvancedReportVariables) {
     292         180 :         SetupOutputVariable(state,
     293         120 :                             format("{} Air Heat Balance Deviation Rate", prefix),
     294             :                             Constant::Units::W,
     295          60 :                             this->imBalance,
     296             :                             OutputProcessor::TimeStepType::System,
     297             :                             OutputProcessor::StoreType::Average,
     298             :                             name);
     299             :     }
     300        5072 : }
     301             : 
     302     2805278 : void SetZoneOutBulbTempAt(EnergyPlusData &state)
     303             : {
     304    22676502 :     for (auto &zone : state.dataHeatBal->Zone) {
     305    19871224 :         zone.SetOutBulbTempAt(state);
     306     2805278 :     }
     307     2805278 : }
     308             : 
     309     2805278 : void CheckZoneOutBulbTempAt(EnergyPlusData &state)
     310             : {
     311             :     // Using/Aliasing
     312             :     using DataEnvironment::SetOutBulbTempAt_error;
     313             : 
     314     2805278 :     Real64 minBulb = 0.0;
     315    22676502 :     for (auto &zone : state.dataHeatBal->Zone) {
     316    19871224 :         minBulb = min(minBulb, zone.OutDryBulbTemp, zone.OutWetBulbTemp);
     317    19871224 :         if (minBulb < -100.0) SetOutBulbTempAt_error(state, "Zone", zone.Centroid.z, zone.Name);
     318     2805278 :     }
     319     2805278 : }
     320             : 
     321     2804482 : void SetZoneWindSpeedAt(EnergyPlusData &state)
     322             : {
     323     2804482 :     Real64 const fac(state.dataEnvrn->WindSpeed * state.dataEnvrn->WeatherFileWindModCoeff *
     324     2804482 :                      std::pow(state.dataEnvrn->SiteWindBLHeight, -state.dataEnvrn->SiteWindExp));
     325    22670650 :     for (auto &zone : state.dataHeatBal->Zone) {
     326    19866168 :         zone.SetWindSpeedAt(state, fac);
     327     2804482 :     }
     328     2804482 : }
     329             : 
     330     2804482 : void SetZoneWindDirAt(EnergyPlusData &state)
     331             : {
     332             :     // Using/Aliasing
     333     2804482 :     Real64 const fac(state.dataEnvrn->WindDir);
     334    22670650 :     for (auto &zone : state.dataHeatBal->Zone) {
     335    19866168 :         zone.SetWindDirAt(fac);
     336     2804482 :     }
     337     2804482 : }
     338             : 
     339        6004 : void CheckAndSetConstructionProperties(EnergyPlusData &state,
     340             :                                        int const ConstrNum, // Construction number to be set/checked
     341             :                                        bool &ErrorsFound    // error flag that is set when certain errors have occurred
     342             : )
     343             : {
     344             : 
     345             :     // SUBROUTINE INFORMATION:
     346             :     //       AUTHOR         Linda Lawrie
     347             :     //       DATE WRITTEN   December 2006
     348             : 
     349             :     // This routine checks some properties of entered constructions; sets some properties; and sets
     350             :     // an error flag for certain error conditions.
     351             : 
     352        6004 :     auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
     353        6004 :     int TotLayers = thisConstruct.TotLayers;                // Number of layers in a construction
     354        6004 :     if (TotLayers == 0) return;                             // error condition, hopefully caught elsewhere
     355        6004 :     int InsideLayer = TotLayers;                            // Inside Layer of Construct; for window construct, layer no. of inside glass
     356        6004 :     if (thisConstruct.LayerPoint(InsideLayer) <= 0) return; // Error condition
     357             : 
     358             :     //   window screen is not allowed on inside layer
     359             : 
     360        6004 :     thisConstruct.DayltPropPtr = 0;
     361        6004 :     int InsideMaterNum = thisConstruct.LayerPoint(InsideLayer); // Material "number" of the Inside layer
     362        6004 :     if (InsideMaterNum != 0) {
     363        6004 :         auto const *mat = state.dataMaterial->Material(InsideMaterNum);
     364        6004 :         thisConstruct.InsideAbsorpVis = mat->AbsorpVisible;
     365        6004 :         thisConstruct.InsideAbsorpSolar = mat->AbsorpSolar;
     366             : 
     367             :         // Following line applies only to opaque surfaces; it is recalculated later for windows.
     368        6004 :         thisConstruct.ReflectVisDiffBack = 1.0 - mat->AbsorpVisible;
     369             :     }
     370             : 
     371        6004 :     int OutsideMaterNum = thisConstruct.LayerPoint(1); // Material "number" of the Outside layer
     372        6004 :     if (OutsideMaterNum != 0) {
     373        6004 :         auto const *mat = state.dataMaterial->Material(OutsideMaterNum);
     374        6004 :         thisConstruct.OutsideAbsorpVis = mat->AbsorpVisible;
     375        6004 :         thisConstruct.OutsideAbsorpSolar = mat->AbsorpSolar;
     376             :     }
     377             : 
     378        6004 :     thisConstruct.TotSolidLayers = 0;
     379        6004 :     thisConstruct.TotGlassLayers = 0;
     380        6004 :     thisConstruct.AbsDiffShade = 0.0;
     381             : 
     382             :     // Check if any layer is glass, gas, shade, screen or blind; if so it is considered a window construction for
     383             :     // purposes of error checking.
     384             : 
     385        6004 :     thisConstruct.TypeIsWindow = false;
     386       20087 :     for (int Layer = 1; Layer <= TotLayers; ++Layer) {
     387       14083 :         int const MaterNum = thisConstruct.LayerPoint(Layer);
     388       14083 :         if (MaterNum == 0) continue; // error -- has been caught will stop program later
     389       14083 :         auto const *thisMaterial = state.dataMaterial->Material(MaterNum);
     390       14083 :         thisConstruct.TypeIsWindow =
     391       12249 :             (thisMaterial->group == Material::Group::WindowGlass || thisMaterial->group == Material::Group::WindowGas ||
     392       11643 :              thisMaterial->group == Material::Group::WindowGasMixture || thisMaterial->group == Material::Group::Shade ||
     393       11616 :              thisMaterial->group == Material::Group::WindowBlind || thisMaterial->group == Material::Group::Screen ||
     394       11596 :              thisMaterial->group == Material::Group::WindowSimpleGlazing || thisMaterial->group == Material::Group::ComplexWindowShade ||
     395       11462 :              thisMaterial->group == Material::Group::ComplexWindowGap || thisMaterial->group == Material::Group::GlassEquivalentLayer ||
     396       11430 :              thisMaterial->group == Material::Group::ShadeEquivalentLayer || thisMaterial->group == Material::Group::DrapeEquivalentLayer ||
     397       37759 :              thisMaterial->group == Material::Group::ScreenEquivalentLayer || thisMaterial->group == Material::Group::BlindEquivalentLayer ||
     398       11427 :              thisMaterial->group == Material::Group::GapEquivalentLayer);
     399       14083 :         bool TypeIsNotWindow = (thisMaterial->group == Material::Group::Invalid || thisMaterial->group == Material::Group::Air ||
     400       30832 :                                 thisMaterial->group == Material::Group::Regular || thisMaterial->group == Material::Group::EcoRoof ||
     401        2666 :                                 thisMaterial->group == Material::Group::IRTransparent);
     402       14083 :         if (!thisConstruct.TypeIsWindow && !TypeIsNotWindow) assert(false);
     403             :     }
     404             : 
     405        6004 :     if (InsideMaterNum == 0) return;
     406        6004 :     auto const *thisMaterialInside = state.dataMaterial->Material(InsideMaterNum);
     407        6004 :     if (OutsideMaterNum == 0) return;
     408        6004 :     auto const *thisMaterialOutside = state.dataMaterial->Material(OutsideMaterNum);
     409             : 
     410        6004 :     if (thisConstruct.TypeIsWindow) {
     411             : 
     412        1331 :         bool WrongMaterialsMix = false;
     413        1331 :         thisConstruct.NumCTFTerms = 0;
     414        1331 :         thisConstruct.NumHistories = 0;
     415        3995 :         for (int Layer = 1; Layer <= TotLayers; ++Layer) {
     416        2664 :             int const MaterNum = thisConstruct.LayerPoint(Layer);
     417        2664 :             if (MaterNum == 0) continue; // error -- has been caught will stop program later
     418        2664 :             auto const *thisMaterial = state.dataMaterial->Material(MaterNum);
     419        2664 :             WrongMaterialsMix =
     420        2888 :                 !((thisMaterial->group == Material::Group::WindowGlass) || (thisMaterial->group == Material::Group::WindowGas) ||
     421         224 :                   (thisMaterial->group == Material::Group::WindowGasMixture) || (thisMaterial->group == Material::Group::Shade) ||
     422         197 :                   (thisMaterial->group == Material::Group::WindowBlind) || (thisMaterial->group == Material::Group::Screen) ||
     423         177 :                   (thisMaterial->group == Material::Group::WindowSimpleGlazing) || (thisMaterial->group == Material::Group::ComplexWindowShade) ||
     424          43 :                   (thisMaterial->group == Material::Group::ComplexWindowGap) || (thisMaterial->group == Material::Group::GlassEquivalentLayer) ||
     425          11 :                   (thisMaterial->group == Material::Group::ShadeEquivalentLayer) || (thisMaterial->group == Material::Group::DrapeEquivalentLayer) ||
     426           9 :                   (thisMaterial->group == Material::Group::ScreenEquivalentLayer) || (thisMaterial->group == Material::Group::BlindEquivalentLayer) ||
     427           8 :                   (thisMaterial->group == Material::Group::GapEquivalentLayer));
     428             :         }
     429             : 
     430        1331 :         if (WrongMaterialsMix) { // Illegal material for a window construction
     431           0 :             ShowSevereError(state,
     432           0 :                             format("Error: Window construction={} has materials other than glass, gas, shade, screen, blind, complex shading, "
     433             :                                    "complex gap, or simple system.",
     434           0 :                                    thisConstruct.Name));
     435           0 :             ErrorsFound = true;
     436             :             // Do not check number of layers for BSDF type of window since that can be handled
     437        1331 :         } else if ((TotLayers > 8) && (!thisConstruct.WindowTypeBSDF) &&
     438           1 :                    (!thisConstruct.WindowTypeEQL)) { // Too many layers for a window construction
     439           0 :             ShowSevereError(state,
     440           0 :                             format("CheckAndSetConstructionProperties: Window construction={} has too many layers (max of 8 allowed -- 4 glass + 3 "
     441             :                                    "gap + 1 shading device).",
     442           0 :                                    thisConstruct.Name));
     443           0 :             ErrorsFound = true;
     444             : 
     445        1331 :         } else if (TotLayers == 1) {
     446         738 :             auto const *thisMaterial = state.dataMaterial->Material(thisConstruct.LayerPoint(1));
     447         738 :             Material::Group thisMaterialGroup = thisMaterial->group;
     448         738 :             if ((thisMaterialGroup == Material::Group::Shade) || (thisMaterialGroup == Material::Group::WindowGas) ||
     449         738 :                 (thisMaterialGroup == Material::Group::WindowGasMixture) || (thisMaterialGroup == Material::Group::WindowBlind) ||
     450         738 :                 (thisMaterialGroup == Material::Group::Screen) || (thisMaterialGroup == Material::Group::ComplexWindowShade) ||
     451             :                 (thisMaterialGroup == Material::Group::ComplexWindowGap)) {
     452           0 :                 ShowSevereError(state,
     453           0 :                                 format("CheckAndSetConstructionProperties: The single-layer window construction={} has a gas, complex gap, shade, "
     454             :                                        "complex shade, screen or blind material; it should be glass of simple glazing system.",
     455           0 :                                        thisConstruct.Name));
     456           0 :                 ErrorsFound = true;
     457             :             }
     458             :         }
     459             : 
     460             :         // Find total glass layers, total shade/blind layers and total gas layers in a window construction
     461             : 
     462        1331 :         bool WrongWindowLayering = false;
     463        1331 :         int TotGlassLayers = 0;
     464        1331 :         int TotShadeLayers = 0; // Includes shades, blinds, and screens
     465        1331 :         int TotGasLayers = 0;
     466        3995 :         for (int Layer = 1; Layer <= TotLayers; ++Layer) {
     467        2664 :             int const MaterNum = thisConstruct.LayerPoint(Layer);
     468        2664 :             if (MaterNum == 0) continue; // error -- has been caught will stop program later
     469        2664 :             auto const *thisMaterial = state.dataMaterial->Material(MaterNum);
     470        2664 :             if (thisMaterial->group == Material::Group::WindowGlass) ++TotGlassLayers;
     471        2664 :             if (thisMaterial->group == Material::Group::WindowSimpleGlazing) ++TotGlassLayers;
     472        2664 :             if (thisMaterial->group == Material::Group::Shade || thisMaterial->group == Material::Group::WindowBlind ||
     473        2634 :                 thisMaterial->group == Material::Group::Screen || thisMaterial->group == Material::Group::ComplexWindowShade)
     474          41 :                 ++TotShadeLayers;
     475        2664 :             if (thisMaterial->group == Material::Group::WindowGas || thisMaterial->group == Material::Group::WindowGasMixture ||
     476        2043 :                 thisMaterial->group == Material::Group::ComplexWindowGap)
     477         645 :                 ++TotGasLayers;
     478        2664 :             if (Layer < TotLayers) {
     479        1333 :                 int const MaterNumNext = thisConstruct.LayerPoint(Layer + 1);
     480             :                 // Adjacent layers of same type not allowed
     481        1333 :                 if (MaterNumNext == 0) continue;
     482        1333 :                 if (thisMaterial->group == state.dataMaterial->Material(MaterNumNext)->group) WrongWindowLayering = true;
     483             :             }
     484             :         }
     485             : 
     486             :         // It is not necessary to check rest of BSDF window structure since that is performed inside TARCOG90 routine.
     487             :         // That routine also allow structures which are not allowed in rest of this routine
     488        1331 :         if (thisConstruct.WindowTypeBSDF) {
     489          14 :             thisConstruct.TotGlassLayers = TotGlassLayers;
     490          14 :             thisConstruct.TotSolidLayers = TotGlassLayers + TotShadeLayers;
     491          14 :             thisConstruct.InsideAbsorpThermal = thisMaterialInside->AbsorpThermalBack;
     492          14 :             thisConstruct.OutsideAbsorpThermal = thisMaterialOutside->AbsorpThermalFront;
     493          14 :             return;
     494             :         }
     495             : 
     496        1317 :         if (thisConstruct.WindowTypeEQL) {
     497           3 :             thisConstruct.InsideAbsorpThermal = thisMaterialInside->AbsorpThermalBack;
     498           3 :             thisConstruct.OutsideAbsorpThermal = thisMaterialOutside->AbsorpThermalFront;
     499           3 :             return;
     500             :         }
     501             : 
     502        1314 :         if (thisMaterialOutside->group == Material::Group::WindowGas || thisMaterialOutside->group == Material::Group::WindowGasMixture ||
     503        1314 :             thisMaterialInside->group == Material::Group::WindowGas || thisMaterialInside->group == Material::Group::WindowGasMixture)
     504           0 :             WrongWindowLayering = true;                     // Gas cannot be first or last layer
     505        1314 :         if (TotShadeLayers > 1) WrongWindowLayering = true; // At most one shade, screen or blind allowed
     506             : 
     507             :         // If there is a diffusing glass layer no shade, screen or blind is allowed
     508        3897 :         for (int Layer = 1; Layer <= TotLayers; ++Layer) {
     509        2583 :             int const MatNum = thisConstruct.LayerPoint(Layer);
     510        2583 :             if (MatNum == 0) continue; // error -- has been caught will stop program later
     511        2583 :             auto const *mat = state.dataMaterial->Material(MatNum);
     512        2583 :             if (mat->group != Material::Group::WindowGlass && mat->group != Material::Group::WindowSimpleGlazing &&
     513         653 :                 mat->group != Material::Group::GlassEquivalentLayer)
     514         653 :                 continue;
     515             : 
     516        1930 :             auto const *matGlass = dynamic_cast<Material::MaterialChild const *>(mat);
     517        1930 :             assert(matGlass != nullptr);
     518        1930 :             if (matGlass->SolarDiffusing && TotShadeLayers > 0) {
     519           0 :                 ErrorsFound = true;
     520           0 :                 ShowSevereError(state, format("CheckAndSetConstructionProperties: Window construction={}", thisConstruct.Name));
     521           0 :                 ShowContinueError(state, format("has diffusing glass={} and a shade, screen or blind layer.", matGlass->Name));
     522           0 :                 break;
     523             :             }
     524             :         }
     525             : 
     526             :         // If there is a diffusing glass layer it must be the innermost layer
     527        1314 :         if (TotGlassLayers > 1) {
     528         556 :             int GlassLayNum = 0;
     529        2361 :             for (int Layer = 1; Layer <= TotLayers; ++Layer) {
     530        1805 :                 int const MatNum = thisConstruct.LayerPoint(Layer);
     531        1805 :                 if (MatNum == 0) continue; // error -- has been caught will stop program later
     532        1805 :                 auto const *mat = state.dataMaterial->Material(MatNum);
     533        1805 :                 if (mat->group != Material::Group::WindowGlass) continue;
     534             : 
     535        1172 :                 auto const *matGlass = dynamic_cast<Material::MaterialChild const *>(mat);
     536        1172 :                 assert(matGlass != nullptr);
     537        1172 :                 ++GlassLayNum;
     538        1172 :                 if (GlassLayNum < TotGlassLayers && matGlass->SolarDiffusing) {
     539           0 :                     ErrorsFound = true;
     540           0 :                     ShowSevereError(state, format("CheckAndSetConstructionProperties: Window construction={}", thisConstruct.Name));
     541           0 :                     ShowContinueError(state, format("has diffusing glass={} that is not the innermost glass layer.", matGlass->Name));
     542             :                 }
     543             :             }
     544             :         }
     545             : 
     546             :         // interior window screen is not allowed. Check for invalid between-glass screen is checked below.
     547        1314 :         if (TotShadeLayers == 1 && thisMaterialInside->group == Material::Group::Screen && TotLayers != 1) {
     548           0 :             WrongWindowLayering = true;
     549             :         }
     550             : 
     551             :         // Consistency checks for a construction with a between-glass shade or blind
     552             : 
     553        1314 :         if (TotShadeLayers == 1 && thisMaterialOutside->group != Material::Group::Shade &&
     554          29 :             thisMaterialOutside->group != Material::Group::WindowBlind && thisMaterialOutside->group != Material::Group::Screen &&
     555          25 :             thisMaterialInside->group != Material::Group::Shade && thisMaterialInside->group != Material::Group::WindowBlind &&
     556           5 :             thisMaterialInside->group != Material::Group::ComplexWindowShade && !WrongWindowLayering) {
     557             : 
     558             :             // This is a construction with a between-glass shade or blind
     559             : 
     560           5 :             if (TotGlassLayers >= 4) {
     561             :                 // Quadruple pane not allowed.
     562           0 :                 WrongWindowLayering = true;
     563           5 :             } else if (TotGlassLayers == 2 || TotGlassLayers == 3) {
     564           5 :                 bool ValidBGShadeBlindConst = false;
     565           5 :                 if (TotGlassLayers == 2) {
     566           3 :                     if (TotLayers != 5) {
     567           0 :                         WrongWindowLayering = true;
     568             :                     } else {
     569           9 :                         if (thisMaterialOutside->group == Material::Group::WindowGlass &&
     570           3 :                             (state.dataMaterial->Material(thisConstruct.LayerPoint(2))->group == Material::Group::WindowGas ||
     571           0 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(2))->group == Material::Group::WindowGasMixture) &&
     572           3 :                             ((state.dataMaterial->Material(thisConstruct.LayerPoint(3))->group == Material::Group::Shade ||
     573           2 :                               state.dataMaterial->Material(thisConstruct.LayerPoint(3))->group == Material::Group::WindowBlind) &&
     574           3 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(3))->group != Material::Group::Screen) &&
     575           3 :                             (state.dataMaterial->Material(thisConstruct.LayerPoint(4))->group == Material::Group::WindowGas ||
     576           6 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(4))->group == Material::Group::WindowGasMixture) &&
     577           3 :                             state.dataMaterial->Material(thisConstruct.LayerPoint(5))->group == Material::Group::WindowGlass)
     578           3 :                             ValidBGShadeBlindConst = true;
     579             :                     }
     580             :                 } else { // TotGlassLayers = 3
     581           2 :                     if (TotLayers != 7) {
     582           0 :                         WrongWindowLayering = true;
     583             :                     } else {
     584           6 :                         if (thisMaterialOutside->group == Material::Group::WindowGlass &&
     585           2 :                             (state.dataMaterial->Material(thisConstruct.LayerPoint(2))->group == Material::Group::WindowGas ||
     586           0 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(2))->group == Material::Group::WindowGasMixture) &&
     587           2 :                             state.dataMaterial->Material(thisConstruct.LayerPoint(3))->group == Material::Group::WindowGlass &&
     588           2 :                             (state.dataMaterial->Material(thisConstruct.LayerPoint(4))->group == Material::Group::WindowGas ||
     589           0 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(4))->group == Material::Group::WindowGasMixture) &&
     590           2 :                             ((state.dataMaterial->Material(thisConstruct.LayerPoint(5))->group == Material::Group::Shade ||
     591           1 :                               state.dataMaterial->Material(thisConstruct.LayerPoint(5))->group == Material::Group::WindowBlind) &&
     592           2 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(5))->group != Material::Group::Screen) &&
     593           2 :                             (state.dataMaterial->Material(thisConstruct.LayerPoint(6))->group == Material::Group::WindowGas ||
     594           4 :                              state.dataMaterial->Material(thisConstruct.LayerPoint(6))->group == Material::Group::WindowGasMixture) &&
     595           2 :                             state.dataMaterial->Material(thisConstruct.LayerPoint(7))->group == Material::Group::WindowGlass)
     596           2 :                             ValidBGShadeBlindConst = true;
     597             :                     }
     598             :                 } // End of check if TotGlassLayers = 2 or 3
     599           5 :                 if (!ValidBGShadeBlindConst) WrongWindowLayering = true;
     600           5 :                 if (!WrongWindowLayering) {
     601           5 :                     int const LayNumSh = 2 * TotGlassLayers - 1;
     602           5 :                     int const MatSh = thisConstruct.LayerPoint(LayNumSh);
     603           5 :                     auto const *thisMaterialSh = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(MatSh));
     604           5 :                     assert(thisMaterialSh != nullptr);
     605             :                     // For double pane, shade/blind must be layer #3.
     606             :                     // For triple pane, it must be layer #5 (i.e., between two inner panes).
     607           5 :                     if (thisMaterialSh->group != Material::Group::Shade && thisMaterialSh->group != Material::Group::WindowBlind)
     608           0 :                         WrongWindowLayering = true;
     609           5 :                     if (TotLayers != 2 * TotGlassLayers + 1) WrongWindowLayering = true;
     610           5 :                     if (!WrongWindowLayering) {
     611             :                         // Gas on either side of a between-glass shade/blind must be the same
     612           5 :                         int const MatGapL = thisConstruct.LayerPoint(LayNumSh - 1);
     613           5 :                         int const MatGapR = thisConstruct.LayerPoint(LayNumSh + 1);
     614           5 :                         auto const *thisMaterialGapL = dynamic_cast<const Material::MaterialGasMix *>(state.dataMaterial->Material(MatGapL));
     615           5 :                         auto const *thisMaterialGapR = dynamic_cast<const Material::MaterialGasMix *>(state.dataMaterial->Material(MatGapR));
     616          30 :                         for (int IGas = 0; IGas < Material::maxMixGases; ++IGas) {
     617          50 :                             if ((thisMaterialGapL->gases[IGas].type != thisMaterialGapR->gases[IGas].type) ||
     618          25 :                                 (thisMaterialGapL->gasFracts[IGas] != thisMaterialGapR->gasFracts[IGas]))
     619           0 :                                 WrongWindowLayering = true;
     620             :                         }
     621             :                         // Gap width on either side of a between-glass shade/blind must be the same
     622           5 :                         if (std::abs(thisMaterialGapL->Thickness - thisMaterialGapR->Thickness) > 0.0005) WrongWindowLayering = true;
     623           5 :                         if (thisMaterialSh->group == Material::Group::WindowBlind) {
     624           3 :                             int const BlNum = thisMaterialSh->BlindDataPtr;
     625           3 :                             if (BlNum > 0) {
     626           3 :                                 if ((thisMaterialGapL->Thickness + thisMaterialGapR->Thickness) < state.dataMaterial->Blind(BlNum).SlatWidth) {
     627           0 :                                     ErrorsFound = true;
     628           0 :                                     ShowSevereError(state,
     629           0 :                                                     format("CheckAndSetConstructionProperties: For window construction {}", thisConstruct.Name));
     630           0 :                                     ShowContinueError(state, "the slat width of the between-glass blind is greater than");
     631           0 :                                     ShowContinueError(state, "the sum of the widths of the gas layers adjacent to the blind.");
     632             :                                 }
     633             :                             } // End of check if BlNum > 0
     634             :                         }     // End of check if material is window blind
     635             :                     }         // End of check if WrongWindowLayering
     636             :                 }             // End of check if WrongWindowLayering
     637             :             }                 // End of check on total glass layers
     638             :         }                     // End of check if construction has between-glass shade/blind
     639             : 
     640             :         // Check Simple Windows,
     641        1314 :         if (state.dataMaterial->Material(thisConstruct.LayerPoint(1))->group == Material::Group::WindowSimpleGlazing) {
     642         124 :             if (TotLayers > 1) {
     643             :                 // check that none of the other layers are glazing or gas
     644          15 :                 for (int Layer = 1; Layer <= TotLayers; ++Layer) {
     645          10 :                     int const MaterNum = thisConstruct.LayerPoint(Layer);
     646          10 :                     if (MaterNum == 0) continue; // error -- has been caught will stop program later
     647          10 :                     auto const *thisMaterial = state.dataMaterial->Material(MaterNum);
     648          10 :                     if (thisMaterial->group == Material::Group::WindowGlass) {
     649           0 :                         ErrorsFound = true;
     650           0 :                         ShowSevereError(state, format("CheckAndSetConstructionProperties: Error in window construction {}--", thisConstruct.Name));
     651           0 :                         ShowContinueError(state, "For simple window constructions, no other glazing layers are allowed.");
     652             :                     }
     653          10 :                     if (thisMaterial->group == Material::Group::WindowGas) {
     654           0 :                         ErrorsFound = true;
     655           0 :                         ShowSevereError(state, format("CheckAndSetConstructionProperties: Error in window construction {}--", thisConstruct.Name));
     656           0 :                         ShowContinueError(state, "For simple window constructions, no other gas layers are allowed.");
     657             :                     }
     658             :                 }
     659             :             }
     660             :         }
     661             : 
     662        1314 :         if (WrongWindowLayering) {
     663           0 :             ShowSevereError(state, format("CheckAndSetConstructionProperties: Error in window construction {}--", thisConstruct.Name));
     664           0 :             ShowContinueError(state, "  For multi-layer window constructions the following rules apply:");
     665           0 :             ShowContinueError(state, "    --The first and last layer must be a solid layer (glass or shade/screen/blind),");
     666           0 :             ShowContinueError(state, "    --Adjacent glass layers must be separated by one and only one gas layer,");
     667           0 :             ShowContinueError(state, "    --Adjacent layers must not be of the same type,");
     668           0 :             ShowContinueError(state, "    --Only one shade/screen/blind layer is allowed,");
     669           0 :             ShowContinueError(state, "    --An exterior shade/screen/blind must be the first layer,");
     670           0 :             ShowContinueError(state, "    --An interior shade/blind must be the last layer,");
     671           0 :             ShowContinueError(state, "    --An interior screen is not allowed,");
     672           0 :             ShowContinueError(state, "    --For an exterior shade/screen/blind or interior shade/blind, there should not be a gas layer");
     673           0 :             ShowContinueError(state, "    ----between the shade/screen/blind and adjacent glass,");
     674           0 :             ShowContinueError(state, "    --A between-glass screen is not allowed,");
     675           0 :             ShowContinueError(state, "    --A between-glass shade/blind is allowed only for double and triple glazing,");
     676           0 :             ShowContinueError(state, "    --A between-glass shade/blind must have adjacent gas layers of the same type and width,");
     677           0 :             ShowContinueError(state, "    --For triple glazing the between-glass shade/blind must be between the two inner glass layers,");
     678           0 :             ShowContinueError(state, "    --The slat width of a between-glass blind must be less than the sum of the widths");
     679           0 :             ShowContinueError(state, "    ----of the gas layers adjacent to the blind.");
     680           0 :             ErrorsFound = true;
     681             :         }
     682             : 
     683        1314 :         thisConstruct.TotGlassLayers = TotGlassLayers;
     684        1314 :         thisConstruct.TotSolidLayers = TotGlassLayers + TotShadeLayers;
     685             : 
     686             :         // In following, InsideLayer is layer number of inside glass and InsideAbsorpThermal applies
     687             :         // only to inside glass; it is corrected later in InitGlassOpticalCalculations
     688             :         // if construction has inside shade or blind.
     689        1314 :         if (thisMaterialInside->group == Material::Group::Shade || thisMaterialInside->group == Material::Group::WindowBlind) {
     690          20 :             --InsideLayer;
     691             :         }
     692        1314 :         if (InsideLayer > 0) {
     693        1314 :             InsideMaterNum = thisConstruct.LayerPoint(InsideLayer);
     694        1314 :             thisConstruct.InsideAbsorpThermal = thisMaterialInside->AbsorpThermalBack;
     695             :         }
     696        1314 :         if (InsideMaterNum != 0) {
     697        1314 :             auto const *thisInsideMaterial = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(InsideMaterNum));
     698        1314 :             thisConstruct.InsideAbsorpVis = thisInsideMaterial->AbsorpVisible;
     699        1314 :             thisConstruct.InsideAbsorpSolar = thisInsideMaterial->AbsorpSolar;
     700             :         }
     701             : 
     702        1314 :         if ((thisMaterialOutside->group == Material::Group::WindowGlass) ||
     703         131 :             (thisMaterialOutside->group == Material::Group::WindowSimpleGlazing)) { // Glass
     704        1307 :             thisConstruct.OutsideAbsorpThermal = thisMaterialOutside->AbsorpThermalFront;
     705             :         } else { // Exterior shade, blind or screen
     706           7 :             thisConstruct.OutsideAbsorpThermal = thisMaterialOutside->AbsorpThermal;
     707             :         }
     708             : 
     709             :     } else { // Opaque surface
     710        4673 :         thisConstruct.InsideAbsorpThermal = thisMaterialInside->AbsorpThermal;
     711        4673 :         thisConstruct.OutsideAbsorpThermal = thisMaterialOutside->AbsorpThermal;
     712             :     }
     713             : 
     714        5987 :     thisConstruct.OutsideRoughness = thisMaterialOutside->Roughness;
     715             : 
     716        5987 :     if (thisMaterialOutside->group == Material::Group::Air) {
     717           0 :         ShowSevereError(state, format("CheckAndSetConstructionProperties: Outside Layer is Air for construction {}", thisConstruct.Name));
     718           0 :         ShowContinueError(state, format("  Error in material {}", thisMaterialOutside->Name));
     719           0 :         ErrorsFound = true;
     720             :     }
     721        5987 :     if (InsideLayer > 0) {
     722        5987 :         if (thisMaterialInside->group == Material::Group::Air) {
     723           0 :             ShowSevereError(state, format("CheckAndSetConstructionProperties: Inside Layer is Air for construction {}", thisConstruct.Name));
     724           0 :             ShowContinueError(state, format("  Error in material {}", thisMaterialInside->Name));
     725           0 :             ErrorsFound = true;
     726             :         }
     727             :     }
     728             : 
     729        5987 :     if (thisMaterialOutside->group == Material::Group::EcoRoof) {
     730           4 :         thisConstruct.TypeIsEcoRoof = true;
     731             :         // need to check EcoRoof is not non-outside layer
     732          12 :         for (int Layer = 2; Layer <= TotLayers; ++Layer) {
     733           8 :             if (state.dataMaterial->Material(thisConstruct.LayerPoint(Layer))->group == Material::Group::EcoRoof) {
     734           0 :                 ShowSevereError(state,
     735           0 :                                 format("CheckAndSetConstructionProperties: Interior Layer is EcoRoof for construction {}", thisConstruct.Name));
     736           0 :                 ShowContinueError(state, format("  Error in material {}", state.dataMaterial->Material(thisConstruct.LayerPoint(Layer))->Name));
     737           0 :                 ErrorsFound = true;
     738             :             }
     739             :         }
     740             :     }
     741             : 
     742        5987 :     if (thisMaterialOutside->group == Material::Group::IRTransparent) {
     743           2 :         thisConstruct.TypeIsIRT = true;
     744           2 :         if (thisConstruct.TotLayers != 1) {
     745           0 :             ShowSevereError(
     746             :                 state,
     747           0 :                 format("CheckAndSetConstructionProperties: Infrared Transparent (IRT) Construction is limited to 1 layer {}", thisConstruct.Name));
     748           0 :             ShowContinueError(state, "  Too many layers in referenced construction.");
     749           0 :             ErrorsFound = true;
     750             :         }
     751             :     }
     752             : }
     753             : 
     754         370 : int AssignReverseConstructionNumber(EnergyPlusData &state,
     755             :                                     int const ConstrNum, // Existing Construction number of first surface
     756             :                                     bool &ErrorsFound)
     757             : {
     758             : 
     759             :     // FUNCTION INFORMATION:
     760             :     //       AUTHOR         Linda Lawrie
     761             :     //       DATE WRITTEN   December 2006
     762             : 
     763             :     // PURPOSE OF THIS FUNCTION:
     764             :     // For interzone, unentered surfaces, we need to have "reverse" constructions
     765             :     // assigned to the created surfaces.  These need to be the reverse (outside to inside layer)
     766             :     // of existing surfaces.  Plus, there may be one already in the data structure so this is looked for as well.
     767             : 
     768             :     // METHODOLOGY EMPLOYED:
     769             :     // Create reverse layers.  Look in current constructions to see if match.  If no match, create a new one.
     770             : 
     771             :     // Return value
     772             :     int NewConstrNum; // Reverse Construction Number
     773             : 
     774         370 :     if (ConstrNum == 0) {
     775             :         // error caught elsewhere
     776           0 :         NewConstrNum = 0;
     777           0 :         return NewConstrNum;
     778             :     }
     779             : 
     780         370 :     auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
     781         370 :     thisConstruct.IsUsed = true;
     782         370 :     int nLayer = 0;
     783         370 :     state.dataConstruction->LayerPoint = 0;
     784        1115 :     for (int Loop = thisConstruct.TotLayers; Loop >= 1; --Loop) {
     785         745 :         ++nLayer;
     786         745 :         state.dataConstruction->LayerPoint(nLayer) = thisConstruct.LayerPoint(Loop);
     787             :     }
     788             : 
     789             :     // now, got thru and see if there is a match already....
     790         370 :     NewConstrNum = 0;
     791        2232 :     for (int Loop = 1; Loop <= state.dataHeatBal->TotConstructs; ++Loop) {
     792        2227 :         bool Found = true;
     793        6249 :         for (nLayer = 1; nLayer <= Construction::MaxLayersInConstruct; ++nLayer) {
     794        5884 :             if (state.dataConstruction->Construct(Loop).LayerPoint(nLayer) != state.dataConstruction->LayerPoint(nLayer)) {
     795        1862 :                 Found = false;
     796        1862 :                 break;
     797             :             }
     798             :         }
     799        2227 :         if (Found) {
     800         365 :             NewConstrNum = Loop;
     801         365 :             state.dataConstruction->Construct(Loop).IsUsed = true;
     802         365 :             break;
     803             :         }
     804             :     }
     805             : 
     806             :     // if need new one, bunch o stuff
     807         370 :     if (NewConstrNum == 0) {
     808           5 :         ++state.dataHeatBal->TotConstructs;
     809           5 :         state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
     810           5 :         state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
     811           5 :         state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs) = 0.0;
     812           5 :         state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
     813           5 :         state.dataHeatBal->NominalU(state.dataHeatBal->TotConstructs) = 0.0;
     814           5 :         state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
     815           5 :         state.dataHeatBal->NominalUBeforeAdjusted(state.dataHeatBal->TotConstructs) = 0.0;
     816           5 :         state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
     817             :         //  Put in new attributes
     818           5 :         NewConstrNum = state.dataHeatBal->TotConstructs;
     819           5 :         state.dataConstruction->Construct(NewConstrNum).IsUsed = true;
     820           5 :         state.dataConstruction->Construct(state.dataHeatBal->TotConstructs) =
     821          10 :             state.dataConstruction->Construct(ConstrNum); // preserve some of the attributes.
     822             :         // replace others...
     823           5 :         state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).Name = "iz-" + state.dataConstruction->Construct(ConstrNum).Name;
     824           5 :         state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
     825          60 :         for (nLayer = 1; nLayer <= Construction::MaxLayersInConstruct; ++nLayer) {
     826          55 :             state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint(nLayer) = state.dataConstruction->LayerPoint(nLayer);
     827          55 :             if (state.dataConstruction->LayerPoint(nLayer) != 0) {
     828          16 :                 state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs) +=
     829          16 :                     state.dataHeatBal->NominalR(state.dataConstruction->LayerPoint(nLayer));
     830             :             }
     831             :         }
     832             : 
     833             :         // no error if zero -- that will have been caught with earlier construction
     834             :         // the following line was changed to fix CR7601
     835           5 :         if (state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs) != 0.0) {
     836           5 :             state.dataHeatBal->NominalU(state.dataHeatBal->TotConstructs) =
     837           5 :                 1.0 / state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs);
     838             :         }
     839             : 
     840           5 :         CheckAndSetConstructionProperties(state, state.dataHeatBal->TotConstructs, ErrorsFound);
     841             :     }
     842             : 
     843         370 :     return NewConstrNum;
     844             : }
     845             : 
     846           3 : void AddVariableSlatBlind(EnergyPlusData &state,
     847             :                           int const inBlindNumber, // current Blind Number/pointer to name
     848             :                           int &outBlindNumber,     // resultant Blind Number to pass back
     849             :                           bool &errFlag            // error flag should one be needed
     850             : )
     851             : {
     852             : 
     853             :     // SUBROUTINE INFORMATION:
     854             :     //       AUTHOR         Linda Lawrie
     855             :     //       DATE WRITTEN   September 2009
     856             :     //       MODIFIED       na
     857             :     //       RE-ENGINEERED  na
     858             : 
     859             :     // PURPOSE OF THIS SUBROUTINE:
     860             :     // Window Blinds are presented as "fixed" slat blinds.  However for certain Window Shading Controls,
     861             :     // the program needs to set the property to "variable"/movable slats.  Since a blind could be in use
     862             :     // elsewhere with "fixed", a material needs to be added with variable properties -- having most of the
     863             :     // "fixed" properties in tact.
     864             : 
     865             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     866             :     int Found;
     867             :     Real64 MinSlatAngGeom;
     868             :     Real64 MaxSlatAngGeom;
     869             : 
     870             :     // Object Data
     871             : 
     872             :     // maybe it's already there
     873           3 :     errFlag = false;
     874           3 :     Found = Util::FindItemInList("~" + state.dataMaterial->Blind(inBlindNumber).Name, state.dataMaterial->Blind);
     875           3 :     if (Found == 0) {
     876             :         // Add a new blind
     877           3 :         state.dataHeatBal->TotBlinds += 1;
     878           3 :         state.dataMaterial->Blind.push_back(Material::WindowBlindProperties());
     879           3 :         state.dataMaterial->Blind(state.dataHeatBal->TotBlinds) = state.dataMaterial->Blind(inBlindNumber);
     880           3 :         state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).Name = "~" + state.dataMaterial->Blind(inBlindNumber).Name;
     881           3 :         outBlindNumber = state.dataHeatBal->TotBlinds;
     882           3 :         state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatAngleType = DataWindowEquivalentLayer::AngleType::Variable;
     883             : 
     884             :         // Minimum and maximum slat angles allowed by slat geometry
     885           3 :         if (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatWidth >
     886           3 :             state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatSeparation) {
     887           3 :             MinSlatAngGeom = std::asin(state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatThickness /
     888           3 :                                        (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatThickness +
     889           3 :                                         state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatSeparation)) /
     890             :                              Constant::DegToRadians;
     891             :         } else {
     892           0 :             MinSlatAngGeom = 0.0;
     893             :         }
     894           3 :         MaxSlatAngGeom = 180.0 - MinSlatAngGeom;
     895             : 
     896             :         // Error if maximum slat angle less than minimum
     897             : 
     898           3 :         if (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle <
     899           3 :             state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle) {
     900           0 :             errFlag = true;
     901           0 :             ShowSevereError(state, format("WindowMaterial:Blind=\"{}\", Illegal value combination.", state.dataMaterial->Blind(inBlindNumber).Name));
     902           0 :             ShowContinueError(state,
     903           0 :                               format("Minimum Slat Angle=[{:.1R}], is greater than Maximum Slat Angle=[{:.1R}] deg.",
     904           0 :                                      state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle,
     905           0 :                                      state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle));
     906             :         }
     907             : 
     908             :         // Error if input slat angle not in input min/max range
     909             : 
     910           3 :         if (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle >
     911           6 :                 state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle &&
     912           3 :             (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatAngle <
     913           3 :                  state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle ||
     914           3 :              state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatAngle >
     915           3 :                  state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle)) {
     916           0 :             errFlag = true;
     917           0 :             ShowSevereError(state, format("WindowMaterial:Blind=\"{}\", Illegal value combination.", state.dataMaterial->Blind(inBlindNumber).Name));
     918           0 :             ShowContinueError(state,
     919           0 :                               format("Slat Angle=[{:.1R}] is outside of the input min/max range, min=[{:.1R}], max=[{:.1R}] deg.",
     920           0 :                                      state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).SlatAngle,
     921           0 :                                      state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle,
     922           0 :                                      state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle));
     923             :         }
     924             : 
     925             :         // Warning if input minimum slat angle is less than that allowed by slat geometry
     926             : 
     927           3 :         if (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle < MinSlatAngGeom) {
     928           3 :             ShowWarningError(state, format("WindowMaterial:Blind=\"{}\", Illegal value combination.", state.dataMaterial->Blind(inBlindNumber).Name));
     929           6 :             ShowContinueError(
     930             :                 state,
     931           6 :                 format("Minimum Slat Angle=[{:.1R}] is less than the smallest allowed by slat dimensions and spacing, min=[{:.1R}] deg.",
     932           3 :                        state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle,
     933             :                        MinSlatAngGeom));
     934           3 :             ShowContinueError(state, format("Minimum Slat Angle will be set to {:.1R} deg.", MinSlatAngGeom));
     935           3 :             state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MinSlatAngle = MinSlatAngGeom;
     936             :         }
     937             : 
     938             :         // Warning if input maximum slat angle is greater than that allowed by slat geometry
     939             : 
     940           3 :         if (state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle > MaxSlatAngGeom) {
     941           3 :             ShowWarningError(state, format("WindowMaterial:Blind=\"{}\", Illegal value combination.", state.dataMaterial->Blind(inBlindNumber).Name));
     942           6 :             ShowContinueError(state,
     943           6 :                               format("Maximum Slat Angle=[{:.1R}] is greater than the largest allowed by slat dimensions and spacing, [{:.1R}] deg.",
     944           3 :                                      state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle,
     945             :                                      MaxSlatAngGeom));
     946           3 :             ShowContinueError(state, format("Maximum Slat Angle will be set to {:.1R} deg.", MaxSlatAngGeom));
     947           3 :             state.dataMaterial->Blind(state.dataHeatBal->TotBlinds).MaxSlatAngle = MaxSlatAngGeom;
     948             :         }
     949             :     } else {
     950           0 :         outBlindNumber = Found;
     951             :     }
     952           3 : }
     953             : 
     954       44408 : Real64 ComputeNominalUwithConvCoeffs(EnergyPlusData &state,
     955             :                                      int const numSurf, // index for Surface array.
     956             :                                      bool &isValid      // returns true if result is valid
     957             : )
     958             : {
     959             : 
     960             :     // SUBROUTINE INFORMATION:
     961             :     //       AUTHOR         Jason Glazer
     962             :     //       DATE WRITTEN   September 2013
     963             :     //       MODIFIED       na
     964             :     //       RE-ENGINEERED  na
     965             : 
     966             :     // PURPOSE OF THIS SUBROUTINE:
     967             :     // Calculate Nominal U-value with convection/film coefficients for reporting by
     968             :     // adding on prescribed R-values for interior and exterior convection coefficients
     969             :     // as found in ASHRAE 90.1-2004, Appendix A. Used in EIO and tabular reports.
     970             :     // ASHRAE 90.1-2004 Section A9.4.1 shows the following:
     971             :     //      R-value Condition
     972             :     //      All exterior conditions                        IP: 0.17  SI: 0.0299
     973             :     //      All semi-exterior surfaces                     IP: 0.46  SI: 0.0810
     974             :     //      Interior horizontal surfaces, heat flow up     IP: 0.61  SI: 0.1074
     975             :     //      Interior horizontal surfaces, heat flow down   IP: 0.92  SI: 0.1620
     976             :     //      Interior vertical surfaces                     IP: 0.68  SI: 0.1198
     977             :     // This section shows the same value in 90.1-2010 and 90.2-2010
     978             :     // Note that this report does not use the semi-exterior surface value because
     979             :     // EnergyPlus does not have a way to specifically tell whether or not a surface
     980             :     // is connected to a semi-exterior area of the building.  Users can always use
     981             :     // the Nominal U-Value to manually calculated this.  The values calculated here
     982             :     // are simply reported to the EIO file and not used for any calculations.
     983             : 
     984             :     // Return value
     985             :     Real64 NominalUwithConvCoeffs; // return value
     986             : 
     987             :     static constexpr std::array<Real64, static_cast<int>(DataSurfaces::SurfaceClass::Num)> filmCoefs = {
     988             :         0.0,       // None
     989             :         0.1197548, // Wall
     990             :         0.1620212, // Floor
     991             :         0.1074271, // Roof
     992             :         0.0,       // IntMass
     993             :         0.0,       // Detached_B
     994             :         0.0,       // Detached_F
     995             :         0.1197548, // Window
     996             :         0.1197548, // GlassDoor
     997             :         0.1197548, // Door
     998             :         0.0,       // Shading
     999             :         0.0,       // Overhang
    1000             :         0.0,       // Fin
    1001             :         0.0,       // TDD_Dome
    1002             :         0.0        // TDD_Diffuser
    1003             :     };             // If anything added to the enum SurfaceClass, adjust this list appropriately
    1004             : 
    1005             :     Real64 insideFilm;
    1006             :     Real64 outsideFilm;
    1007             : 
    1008       44408 :     isValid = true;
    1009             : 
    1010       44408 :     auto &thisSurface = state.dataSurface->Surface(numSurf);
    1011             : 
    1012             :     // exterior conditions
    1013       44408 :     switch (thisSurface.ExtBoundCond) {
    1014       17799 :     case DataSurfaces::ExternalEnvironment: { // ExtBoundCond = 0
    1015       17799 :         outsideFilm = 0.0299387;              // All exterior conditions
    1016       17799 :     } break;
    1017           1 :     case DataSurfaces::OtherSideCoefCalcExt: {
    1018           1 :         outsideFilm = state.dataSurface->OSC(thisSurface.OSCPtr).SurfFilmCoef;
    1019           1 :     } break;
    1020        2510 :     case DataSurfaces::Ground:
    1021             :     case DataSurfaces::OtherSideCoefNoCalcExt:
    1022             :     case DataSurfaces::OtherSideCondModeledExt:
    1023             :     case DataSurfaces::GroundFCfactorMethod:
    1024             :     case DataSurfaces::KivaFoundation: { // All these cases have a negative ExtBoundCond so don't use film coefficients
    1025        2510 :         outsideFilm = 0.0;
    1026        2510 :     } break;
    1027       24098 :     default: { // Interior Surface Attached to a Zone (ExtBoundCond is a surface)
    1028       24098 :         outsideFilm = filmCoefs[static_cast<int>(state.dataSurface->Surface(thisSurface.ExtBoundCond).Class)];
    1029       24098 :     } break;
    1030             :     }
    1031             :     // interior conditions and calculate the return value
    1032       44408 :     if (state.dataHeatBal->NominalU(thisSurface.Construction) > 0.0) {
    1033       44390 :         insideFilm = filmCoefs[static_cast<int>(thisSurface.Class)];
    1034       44390 :         if (insideFilm == 0.0) outsideFilm = 0.0;
    1035       44390 :         NominalUwithConvCoeffs =
    1036       44390 :             1.0 / (insideFilm + (1.0 / state.dataHeatBal->NominalU(state.dataSurface->Surface(numSurf).Construction)) + outsideFilm);
    1037             :     } else {
    1038          18 :         isValid = false;
    1039          18 :         NominalUwithConvCoeffs = state.dataHeatBal->NominalU(state.dataSurface->Surface(numSurf).Construction);
    1040             :     }
    1041             : 
    1042       44408 :     return NominalUwithConvCoeffs;
    1043             : }
    1044             : 
    1045         796 : void SetFlagForWindowConstructionWithShadeOrBlindLayer(EnergyPlusData &state)
    1046             : {
    1047             : 
    1048             :     // PURPOSE OF THIS SUBROUTINE:
    1049             :     // check fenestrations with shading control and set a flag to true if its construction has
    1050             :     // either shade or blind material layer
    1051             : 
    1052             :     // METHODOLOGY EMPLOYED:
    1053             :     // Loop through Surface and register any shading controls, and loop through the construction
    1054             :     // material layer
    1055             : 
    1056             :     // Using/Aliasing
    1057             :     using DataSurfaces::ExternalEnvironment;
    1058             : 
    1059             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1060         796 :     int loopSurfNum(0); // surface index
    1061         796 :     int ConstrNum(0);   // construction index
    1062         796 :     int NumLayers(0);   // number of material layers in a construction
    1063         796 :     int Layer(0);       // construction material layer index
    1064         796 :     int MaterNum(0);    // construction material index
    1065             : 
    1066       46840 :     for (loopSurfNum = 1; loopSurfNum <= state.dataSurface->TotSurfaces; ++loopSurfNum) {
    1067             : 
    1068       46044 :         if (state.dataSurface->Surface(loopSurfNum).Class != DataSurfaces::SurfaceClass::Window) continue;
    1069        6217 :         if (state.dataSurface->Surface(loopSurfNum).ExtBoundCond != ExternalEnvironment) continue;
    1070        6203 :         if (!state.dataSurface->Surface(loopSurfNum).HasShadeControl) continue;
    1071         151 :         if (state.dataSurface->Surface(loopSurfNum).activeShadedConstruction == 0) continue;
    1072             : 
    1073         151 :         ConstrNum = state.dataSurface->Surface(loopSurfNum).activeShadedConstruction;
    1074         151 :         auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    1075         151 :         if (thisConstruct.TypeIsWindow) {
    1076         151 :             NumLayers = thisConstruct.TotLayers;
    1077         610 :             for (Layer = 1; Layer <= NumLayers; ++Layer) {
    1078         459 :                 MaterNum = thisConstruct.LayerPoint(Layer);
    1079         459 :                 if (MaterNum == 0) continue;
    1080         459 :                 auto const *thisMaterial = state.dataMaterial->Material(MaterNum);
    1081         459 :                 if (thisMaterial->group == Material::Group::Shade || thisMaterial->group == Material::Group::WindowBlind)
    1082         113 :                     state.dataSurface->SurfWinHasShadeOrBlindLayer(loopSurfNum) = true;
    1083             :             }
    1084             :         }
    1085             :     }
    1086         796 : }
    1087             : 
    1088         796 : void AllocateIntGains(EnergyPlusData &state)
    1089             : {
    1090         796 :     state.dataHeatBal->ZoneIntGain.allocate(state.dataGlobal->NumOfZones);
    1091         796 :     state.dataHeatBal->spaceIntGain.allocate(state.dataGlobal->numSpaces);
    1092         796 :     state.dataHeatBal->spaceIntGainDevices.allocate(state.dataGlobal->numSpaces);
    1093         796 :     state.dataDayltg->spacePowerReductionFactor.dimension(state.dataGlobal->numSpaces, 1.0);
    1094         796 : }
    1095             : 
    1096             : } // namespace EnergyPlus::DataHeatBalance

Generated by: LCOV version 1.14