LCOV - code coverage report
Current view: top level - EnergyPlus - Material.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 62.2 % 2097 1305
Test Date: 2025-06-02 07:23:51 Functions: 84.6 % 13 11

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // ObjexxFCL Headers
      49              : #include <ObjexxFCL/Array.functions.hh>
      50              : 
      51              : // EnergyPlus Headers
      52              : #include <EnergyPlus/CurveManager.hh>
      53              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      54              : #include <EnergyPlus/DataEnvironment.hh>
      55              : #include <EnergyPlus/DataIPShortCuts.hh>
      56              : #include <EnergyPlus/EMSManager.hh>
      57              : #include <EnergyPlus/General.hh>
      58              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      59              : #include <EnergyPlus/Material.hh>
      60              : #include <EnergyPlus/ScheduleManager.hh>
      61              : #include <EnergyPlus/UtilityRoutines.hh>
      62              : #include <EnergyPlus/WindowModel.hh>
      63              : 
      64              : namespace EnergyPlus::Material {
      65              : 
      66              : constexpr std::array<std::string_view, (int)GapVentType::Num> gapVentTypeNames = {"Sealed", "VentedIndoor", "VentedOutdoor"};
      67              : constexpr std::array<std::string_view, (int)GasType::Num> gasTypeNames = {"Custom", "Air", "Argon", "Krypton", "Xenon"};
      68              : constexpr std::array<std::string_view, (int)GasType::Num> gasTypeNamesUC = {"CUSTOM", "AIR", "ARGON", "KRYPTON", "XENON"};
      69              : constexpr std::array<std::string_view, (int)SurfaceRoughness::Num> surfaceRoughnessNames = {
      70              :     "VeryRough", "Rough", "MediumRough", "MediumSmooth", "Smooth", "VerySmooth"};
      71              : 
      72              : constexpr std::array<Material::Gas, 10> gases = {
      73              :     Gas(),                                                                                                        // Empty
      74              :     {GasType::Air, {2.873e-3, 7.760e-5, 0.0}, {3.723e-6, 4.940e-8, 0.0}, {1002.737, 1.2324e-2, 0.0}, 28.97, 1.4}, // Air
      75              :     {GasType::Argon, {2.285e-3, 5.149e-5, 0.0}, {3.379e-6, 6.451e-8, 0.0}, {521.929, 0.0, 0.0}, 39.948, 1.67},    // Argon
      76              :     {GasType::Krypton, {9.443e-4, 2.826e-5, 0.0}, {2.213e-6, 7.777e-8, 0.0}, {248.091, 0.0, 0.0}, 83.8, 1.68},    // Krypton
      77              :     {GasType::Xenon, {4.538e-4, 1.723e-5, 0.0}, {1.069e-6, 7.414e-8, 0.0}, {158.340, 0.0, 0.0}, 131.3, 1.66},     // Xenon
      78              :     Gas(),                                                                                                        // Empty
      79              :     Gas(),                                                                                                        // Empty
      80              :     Gas(),                                                                                                        // Empty
      81              :     Gas(),                                                                                                        // Empty
      82              :     Gas()                                                                                                         // Empty
      83              : };
      84              : 
      85              : constexpr std::array<std::string_view, (int)EcoRoofCalcMethod::Num> ecoRoofCalcMethodNamesUC = {"SIMPLE", "ADVANCED"};
      86              : 
      87        14215 : int GetMaterialNum(EnergyPlusData const &state, std::string const &matName)
      88              : {
      89        14215 :     auto const &s_mat = state.dataMaterial;
      90        14215 :     auto found = s_mat->materialMap.find(Util::makeUPPER(matName));
      91        28430 :     return (found != s_mat->materialMap.end()) ? found->second : 0;
      92        14215 : }
      93              : 
      94            0 : MaterialBase *GetMaterial(EnergyPlusData &state, std::string const &matName)
      95              : {
      96            0 :     auto &s_mat = state.dataMaterial;
      97            0 :     int matNum = GetMaterialNum(state, matName);
      98            0 :     return (matNum > 0) ? s_mat->materials(matNum) : nullptr;
      99              : }
     100              : 
     101          801 : void GetMaterialData(EnergyPlusData &state, bool &ErrorsFound) // set to true if errors found in input
     102              : {
     103              : 
     104              :     // SUBROUTINE INFORMATION:
     105              :     //       AUTHOR         Richard Liesen
     106              :     //       DATE WRITTEN   September 1997
     107              :     //       MODIFIED       April 1999; L.Lawrie
     108              :     //                      Sept 1999, FCW, Window5 modifications
     109              :     //                      Mar 2001, FCW, WindowShade mods
     110              :     //                      Sep 2001, FCW, add Material:WindowGasMixture
     111              :     //                      Oct 2001, FCW, add Material:WindowBlind
     112              :     //                      Dec 2003, FCW, add glass solar/visible transmittance dirt factor
     113              :     //                      Feb 2009, TH, added WindowMaterial:GlazingGroup:Thermochromic
     114              : 
     115              :     //       RE-ENGINEERED  na
     116              : 
     117              :     // PURPOSE OF THIS SUBROUTINE:
     118              :     // The purpose of this subroutine is to serve as a transfer agent
     119              :     // between the input file and the material derived type.  The new input
     120              :     // file is working, and this file reads the material data directly
     121              :     // from the input file and transfer that information to the new data
     122              :     // structure.  Data read in this routine is stored in a
     123              :     // derived type (Material) defined in the DataHeatBalance module.
     124              : 
     125              :     // In April 1999, a new set of material definitions replaced the one "all-purpose"
     126              :     // material definition.  There are now 10 flavors of materials.  Definitions from
     127              :     // the IDD appear below before their counterpart "gets".
     128              : 
     129              :     using Curve::GetCurveIndex;
     130              :     using Curve::GetCurveMinMaxValues;
     131              : 
     132              :     using General::ScanForReports;
     133              : 
     134              :     int IOStat;    // IO Status when calling get input subroutine
     135              :     int NumAlphas; // Number of material alpha names being passed
     136              :     int NumNums;   // Number of material properties being passed
     137              : 
     138              :     int NumGas;                         // Index for loop over gap gases in a mixture
     139              :     int NumGases;                       // Number of gasses in a mixture
     140          801 :     GasType gasType = GasType::Invalid; // Gas type index: 1=air, 2=argon, 3=krypton, 4=xenon
     141              :     int ICoeff;                         // Gas property coefficient index
     142              :     Real64 MinSlatAngGeom;              // Minimum and maximum slat angle allowed by slat geometry (deg)
     143              :     Real64 MaxSlatAngGeom;
     144              :     Real64 ReflectivitySol;   // Glass reflectivity, solar
     145              :     Real64 ReflectivityVis;   // Glass reflectivity, visible
     146              :     Real64 TransmittivitySol; // Glass transmittivity, solar
     147              :     Real64 TransmittivityVis; // Glass transmittivity, visible
     148              :     Real64 DenomRGas;         // Denominator for WindowGas calculations of NominalR
     149              :     Real64 Openness;          // insect screen openness fraction = (1-d/s)^2
     150              :     Real64 minAngValue;       // minimum value of angle
     151              :     Real64 maxAngValue;       // maximum value of angle
     152              :     Real64 minLamValue;       // minimum value of wavelength
     153              :     Real64 maxLamValue;       // maximum value of wavelength
     154              : 
     155              :     // Added TH 1/9/2009 to read the thermochromic glazings
     156              : 
     157              :     // Added TH 7/27/2009 for constructions defined with F or C factor method
     158              :     int TotFfactorConstructs; // Number of slabs-on-grade or underground floor constructions defined with F factors
     159              :     int TotCfactorConstructs; // Number of underground wall constructions defined with C factors
     160              : 
     161              :     static constexpr std::string_view routineName = "GetMaterialData";
     162              : 
     163          801 :     auto &s_mat = state.dataMaterial;
     164          801 :     auto &s_ip = state.dataInputProcessing->inputProcessor;
     165          801 :     auto &s_ipsc = state.dataIPShortCut;
     166              : 
     167          801 :     s_mat->NumNoMasses = s_ip->getNumObjectsFound(state, "Material:NoMass");
     168          801 :     s_mat->NumIRTs = s_ip->getNumObjectsFound(state, "Material:InfraredTransparent");
     169          801 :     s_mat->NumAirGaps = s_ip->getNumObjectsFound(state, "Material:AirGap");
     170              : 
     171          801 :     TotFfactorConstructs = s_ip->getNumObjectsFound(state, "Construction:FfactorGroundFloor");
     172          801 :     TotCfactorConstructs = s_ip->getNumObjectsFound(state, "Construction:CfactorUndergroundWall");
     173              : 
     174              :     // Regular Materials
     175              : 
     176          801 :     s_ipsc->cCurrentModuleObject = "Material";
     177          801 :     auto const instances = s_ip->epJSON.find(s_ipsc->cCurrentModuleObject);
     178          801 :     if (instances != s_ip->epJSON.end()) {
     179          768 :         auto const &objectSchemaProps = s_ip->getObjectSchemaProps(state, s_ipsc->cCurrentModuleObject);
     180              : 
     181          768 :         auto &instancesValue = instances.value();
     182              : 
     183          768 :         std::vector<std::string> idfSortedKeys = s_ip->getIDFOrderedKeys(state, s_ipsc->cCurrentModuleObject);
     184         9463 :         for (std::string const &key : idfSortedKeys) {
     185              : 
     186         8695 :             auto instance = instancesValue.find(key);
     187         8695 :             assert(instance != instancesValue.end());
     188              : 
     189         8695 :             auto const &objectFields = instance.value();
     190         8695 :             std::string matNameUC = Util::makeUPPER(key);
     191         8695 :             s_ip->markObjectAsUsed(s_ipsc->cCurrentModuleObject, key);
     192              : 
     193         8695 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, key};
     194              : 
     195         8695 :             if (s_mat->materialMap.find(matNameUC) != s_mat->materialMap.end()) {
     196            0 :                 ShowSevereDuplicateName(state, eoh);
     197            0 :                 ErrorsFound = true;
     198            0 :                 continue;
     199              :             }
     200              : 
     201              :             // Load the material derived type from the input data.
     202         8695 :             auto *mat = new MaterialBase;
     203         8695 :             mat->group = Group::Regular;
     204         8695 :             mat->Name = key;
     205              : 
     206         8695 :             s_mat->materials.push_back(mat);
     207         8695 :             mat->Num = s_mat->materials.isize();
     208         8695 :             s_mat->materialMap.insert_or_assign(matNameUC, mat->Num);
     209              : 
     210        17390 :             std::string roughness = s_ip->getAlphaFieldValue(objectFields, objectSchemaProps, "roughness");
     211         8695 :             mat->Roughness = static_cast<SurfaceRoughness>(getEnumValue(surfaceRoughnessNamesUC, Util::makeUPPER(roughness)));
     212        17390 :             mat->Thickness = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "thickness");
     213        17390 :             mat->Conductivity = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "conductivity");
     214        17390 :             mat->Density = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "density");
     215        17390 :             mat->SpecHeat = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "specific_heat");
     216        17390 :             mat->AbsorpThermal = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "thermal_absorptance");
     217         8695 :             mat->AbsorpThermalInput = mat->AbsorpThermal;
     218        17390 :             mat->AbsorpSolar = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "solar_absorptance");
     219         8695 :             mat->AbsorpSolarInput = mat->AbsorpSolar;
     220        17390 :             mat->AbsorpVisible = s_ip->getRealFieldValue(objectFields, objectSchemaProps, "visible_absorptance");
     221         8695 :             mat->AbsorpVisibleInput = mat->AbsorpVisible;
     222              : 
     223         8695 :             if (mat->Conductivity > 0.0) {
     224         8695 :                 mat->Resistance = mat->NominalR = mat->Thickness / mat->Conductivity;
     225              :             } else {
     226            0 :                 ShowSevereError(state, format("Positive thermal conductivity required for material {}", mat->Name));
     227            0 :                 ErrorsFound = true;
     228              :             }
     229         9463 :         }
     230          768 :     }
     231              : 
     232              :     // Add the 6" heavy concrete for constructions defined with F or C factor method
     233          801 :     if (TotFfactorConstructs + TotCfactorConstructs >= 1) {
     234           21 :         auto *mat = new MaterialBase;
     235           21 :         mat->group = Group::Regular;
     236           21 :         mat->Name = "~FC_Concrete";
     237              : 
     238           21 :         s_mat->materials.push_back(mat);
     239           21 :         mat->Num = s_mat->materials.isize();
     240           21 :         s_mat->materialMap.insert_or_assign(Util::makeUPPER(mat->Name), mat->Num);
     241              : 
     242           21 :         mat->Thickness = 0.15;    // m, 0.15m = 6 inches
     243           21 :         mat->Conductivity = 1.95; // W/mK
     244           21 :         mat->Density = 2240.0;    // kg/m3
     245           21 :         mat->SpecHeat = 900.0;    // J/kgK
     246           21 :         mat->Roughness = SurfaceRoughness::MediumRough;
     247           21 :         mat->AbsorpSolar = 0.7;
     248           21 :         mat->AbsorpThermal = 0.9;
     249           21 :         mat->AbsorpVisible = 0.7;
     250           21 :         mat->Resistance = mat->NominalR = mat->Thickness / mat->Conductivity;
     251              :     }
     252              : 
     253          801 :     s_ipsc->cCurrentModuleObject = "Material:NoMass";
     254         2605 :     for (int Loop = 1; Loop <= s_mat->NumNoMasses; ++Loop) {
     255              : 
     256              :         // Call Input Get routine to retrieve material data
     257         3608 :         s_ip->getObjectItem(state,
     258         1804 :                             s_ipsc->cCurrentModuleObject,
     259              :                             Loop,
     260         1804 :                             s_ipsc->cAlphaArgs,
     261              :                             NumAlphas,
     262         1804 :                             s_ipsc->rNumericArgs,
     263              :                             NumNums,
     264              :                             IOStat,
     265         1804 :                             s_ipsc->lNumericFieldBlanks,
     266         1804 :                             s_ipsc->lAlphaFieldBlanks,
     267         1804 :                             s_ipsc->cAlphaFieldNames,
     268         1804 :                             s_ipsc->cNumericFieldNames);
     269              : 
     270         1804 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     271              : 
     272         1804 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     273            0 :             ShowSevereDuplicateName(state, eoh);
     274            0 :             ErrorsFound = true;
     275            0 :             continue;
     276              :         }
     277              : 
     278         1804 :         auto *mat = new MaterialBase;
     279         1804 :         mat->group = Group::Regular;
     280         1804 :         mat->Name = s_ipsc->cAlphaArgs(1);
     281              : 
     282         1804 :         s_mat->materials.push_back(mat);
     283         1804 :         mat->Num = s_mat->materials.isize();
     284         1804 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
     285              : 
     286         1804 :         mat->Roughness = static_cast<SurfaceRoughness>(getEnumValue(surfaceRoughnessNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(2))));
     287              : 
     288         1804 :         mat->Resistance = s_ipsc->rNumericArgs(1);
     289         1804 :         mat->ROnly = true;
     290         1804 :         if (NumNums >= 2) {
     291         1667 :             mat->AbsorpThermal = s_ipsc->rNumericArgs(2);
     292         1667 :             mat->AbsorpThermalInput = s_ipsc->rNumericArgs(2);
     293              :         } else {
     294          137 :             mat->AbsorpThermal = 0.9;
     295          137 :             mat->AbsorpThermalInput = 0.9;
     296              :         }
     297         1804 :         if (NumNums >= 3) {
     298         1667 :             mat->AbsorpSolar = s_ipsc->rNumericArgs(3);
     299         1667 :             mat->AbsorpSolarInput = s_ipsc->rNumericArgs(3);
     300              :         } else {
     301          137 :             mat->AbsorpSolar = 0.7;
     302          137 :             mat->AbsorpSolarInput = 0.7;
     303              :         }
     304         1804 :         if (NumNums >= 4) {
     305         1562 :             mat->AbsorpVisible = s_ipsc->rNumericArgs(4);
     306         1562 :             mat->AbsorpVisibleInput = s_ipsc->rNumericArgs(4);
     307              :         } else {
     308          242 :             mat->AbsorpVisible = 0.7;
     309          242 :             mat->AbsorpVisibleInput = 0.7;
     310              :         }
     311              : 
     312         1804 :         mat->NominalR = mat->Resistance;
     313              :     }
     314              : 
     315              :     // Add a fictitious insulation layer for each construction defined with F or C factor method
     316          801 :     if (TotFfactorConstructs + TotCfactorConstructs >= 1) {
     317          238 :         for (int Loop = 1; Loop <= TotFfactorConstructs + TotCfactorConstructs; ++Loop) {
     318          217 :             auto *mat = new MaterialBase;
     319          217 :             mat->group = Group::Regular;
     320          217 :             mat->Name = format("~FC_Insulation_{}", Loop);
     321              : 
     322          217 :             s_mat->materials.push_back(mat);
     323          217 :             mat->Num = s_mat->materials.isize();
     324          217 :             s_mat->materialMap.insert_or_assign(Util::makeUPPER(mat->Name), mat->Num);
     325              : 
     326          217 :             mat->ROnly = true;
     327          217 :             mat->Roughness = SurfaceRoughness::MediumRough;
     328          217 :             mat->AbsorpSolar = 0.0;
     329          217 :             mat->AbsorpThermal = 0.0;
     330          217 :             mat->AbsorpVisible = 0.0;
     331              :         }
     332              :     }
     333              : 
     334              :     // Air Materials (for air spaces in opaque constructions)
     335          801 :     s_ipsc->cCurrentModuleObject = "Material:AirGap";
     336         1345 :     for (int Loop = 1; Loop <= s_mat->NumAirGaps; ++Loop) {
     337              : 
     338              :         // Call Input Get routine to retrieve material data
     339         1088 :         s_ip->getObjectItem(state,
     340          544 :                             s_ipsc->cCurrentModuleObject,
     341              :                             Loop,
     342          544 :                             s_ipsc->cAlphaArgs,
     343              :                             NumAlphas,
     344          544 :                             s_ipsc->rNumericArgs,
     345              :                             NumNums,
     346              :                             IOStat,
     347          544 :                             s_ipsc->lNumericFieldBlanks,
     348          544 :                             s_ipsc->lAlphaFieldBlanks,
     349          544 :                             s_ipsc->cAlphaFieldNames,
     350          544 :                             s_ipsc->cNumericFieldNames);
     351              : 
     352          544 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     353              : 
     354          544 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     355            0 :             ShowSevereDuplicateName(state, eoh);
     356            0 :             ErrorsFound = true;
     357            0 :             continue;
     358              :         }
     359              : 
     360              :         // Load the material derived type from the input data.
     361          544 :         auto *mat = new MaterialBase;
     362          544 :         mat->group = Group::AirGap;
     363          544 :         mat->Name = s_ipsc->cAlphaArgs(1);
     364              : 
     365          544 :         s_mat->materials.push_back(mat);
     366          544 :         mat->Num = s_mat->materials.isize();
     367          544 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
     368              : 
     369          544 :         mat->Roughness = SurfaceRoughness::MediumRough;
     370              : 
     371          544 :         mat->NominalR = mat->Resistance = s_ipsc->rNumericArgs(1);
     372          544 :         mat->ROnly = true;
     373              :     }
     374              : 
     375          801 :     s_ipsc->cCurrentModuleObject = "Material:InfraredTransparent";
     376          804 :     for (int Loop = 1; Loop <= s_mat->NumIRTs; ++Loop) {
     377              : 
     378              :         // Call Input Get routine to retrieve material data
     379            6 :         s_ip->getObjectItem(state,
     380            3 :                             s_ipsc->cCurrentModuleObject,
     381              :                             Loop,
     382            3 :                             s_ipsc->cAlphaArgs,
     383              :                             NumAlphas,
     384            3 :                             s_ipsc->rNumericArgs,
     385              :                             NumNums,
     386              :                             IOStat,
     387            3 :                             s_ipsc->lNumericFieldBlanks,
     388            3 :                             s_ipsc->lAlphaFieldBlanks,
     389            3 :                             s_ipsc->cAlphaFieldNames,
     390            3 :                             s_ipsc->cNumericFieldNames);
     391              : 
     392            3 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     393              : 
     394            3 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     395            0 :             ShowSevereDuplicateName(state, eoh);
     396            0 :             ErrorsFound = true;
     397            0 :             continue;
     398              :         }
     399              : 
     400            3 :         auto *mat = new MaterialBase;
     401            3 :         mat->group = Group::IRTransparent;
     402            3 :         mat->Name = s_ipsc->cAlphaArgs(1);
     403              : 
     404            3 :         s_mat->materials.push_back(mat);
     405            3 :         mat->Num = s_mat->materials.isize();
     406            3 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
     407              : 
     408              :         // Load data for other properties that need defaults
     409            3 :         mat->ROnly = true;
     410            3 :         mat->NominalR = mat->Resistance = 0.01;
     411            3 :         mat->AbsorpThermal = 0.9999;
     412            3 :         mat->AbsorpThermalInput = 0.9999;
     413            3 :         mat->AbsorpSolar = 1.0;
     414            3 :         mat->AbsorpSolarInput = 1.0;
     415            3 :         mat->AbsorpVisible = 1.0;
     416            3 :         mat->AbsorpVisibleInput = 1.0;
     417              :     }
     418              : 
     419              :     // Glass materials, regular input: transmittance and front/back reflectance
     420              : 
     421          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Glazing";
     422          801 :     s_mat->NumW5Glazings = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     423         2527 :     for (int Loop = 1; Loop <= s_mat->NumW5Glazings; ++Loop) {
     424              : 
     425              :         // Call Input Get routine to retrieve material data
     426         3452 :         s_ip->getObjectItem(state,
     427         1726 :                             s_ipsc->cCurrentModuleObject,
     428              :                             Loop,
     429         1726 :                             s_ipsc->cAlphaArgs,
     430              :                             NumAlphas,
     431         1726 :                             s_ipsc->rNumericArgs,
     432              :                             NumNums,
     433              :                             IOStat,
     434         1726 :                             s_ipsc->lNumericFieldBlanks,
     435         1726 :                             s_ipsc->lAlphaFieldBlanks,
     436         1726 :                             s_ipsc->cAlphaFieldNames,
     437         1726 :                             s_ipsc->cNumericFieldNames);
     438              : 
     439         1726 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     440              : 
     441         1726 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     442            0 :             ShowSevereDuplicateName(state, eoh);
     443            0 :             ErrorsFound = true;
     444            0 :             continue;
     445              :         }
     446              : 
     447         1726 :         auto *mat = new MaterialGlass;
     448         1726 :         mat->Name = s_ipsc->cAlphaArgs(1);
     449              : 
     450         1726 :         s_mat->materials.push_back(mat);
     451         1726 :         mat->Num = s_mat->materials.isize();
     452         1726 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
     453              : 
     454         1726 :         mat->Roughness = SurfaceRoughness::VerySmooth;
     455         1726 :         mat->ROnly = true;
     456         1726 :         mat->Thickness = s_ipsc->rNumericArgs(1);
     457              : 
     458         1726 :         mat->windowOpticalData = static_cast<Window::OpticalDataModel>(getEnumValue(Window::opticalDataModelNamesUC, s_ipsc->cAlphaArgs(2)));
     459         1726 :         if (mat->windowOpticalData != Window::OpticalDataModel::SpectralAndAngle) {
     460         1725 :             mat->Trans = s_ipsc->rNumericArgs(2);
     461         1725 :             mat->ReflectSolBeamFront = s_ipsc->rNumericArgs(3);
     462         1725 :             mat->ReflectSolBeamBack = s_ipsc->rNumericArgs(4);
     463         1725 :             mat->TransVis = s_ipsc->rNumericArgs(5);
     464         1725 :             mat->ReflectVisBeamFront = s_ipsc->rNumericArgs(6);
     465         1725 :             mat->ReflectVisBeamBack = s_ipsc->rNumericArgs(7);
     466         1725 :             mat->TransThermal = s_ipsc->rNumericArgs(8);
     467              :         }
     468         1726 :         mat->AbsorpThermalFront = s_ipsc->rNumericArgs(9);
     469         1726 :         mat->AbsorpThermalBack = s_ipsc->rNumericArgs(10);
     470         1726 :         mat->Conductivity = s_ipsc->rNumericArgs(11);
     471         1726 :         mat->GlassTransDirtFactor = s_ipsc->rNumericArgs(12);
     472         1726 :         mat->YoungModulus = s_ipsc->rNumericArgs(13);
     473         1726 :         mat->PoissonsRatio = s_ipsc->rNumericArgs(14);
     474         1726 :         if (s_ipsc->rNumericArgs(12) == 0.0) {
     475            0 :             mat->GlassTransDirtFactor = 1.0;
     476              :         }
     477         1726 :         mat->AbsorpThermal = mat->AbsorpThermalBack;
     478              : 
     479         1726 :         if (mat->Conductivity > 0.0) {
     480         1726 :             mat->Resistance = mat->NominalR = mat->Thickness / mat->Conductivity;
     481              :         } else {
     482            0 :             ErrorsFound = true;
     483            0 :             ShowSevereError(state, format("Window glass material {} has Conductivity = 0.0, must be >0.0, default = .9", mat->Name));
     484              :         }
     485              : 
     486         1726 :         mat->windowOpticalData = static_cast<Window::OpticalDataModel>(getEnumValue(Window::opticalDataModelNamesUC, s_ipsc->cAlphaArgs(2)));
     487              : 
     488         1726 :         if (mat->windowOpticalData == Window::OpticalDataModel::Spectral) {
     489           83 :             if (s_ipsc->lAlphaFieldBlanks(3)) {
     490            0 :                 ShowSevereCustom(state, eoh, format("{} = Spectral but {} is blank.", s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaFieldNames(3)));
     491            0 :                 ErrorsFound = true;
     492           83 :             } else if ((mat->GlassSpectralDataPtr = Util::FindItemInList(s_ipsc->cAlphaArgs(3), s_mat->SpectralData)) == 0) {
     493            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3));
     494            0 :                 ErrorsFound = true;
     495              :             }
     496              : 
     497              :             // TH 8/24/2011, allow glazing properties s_ipsc->rNumericArgs(2 to 10) to equal 0 or 1: 0.0 =< Prop <= 1.0
     498              :             // Fixed CR 8413 - modeling spandrel panels as glazing systems
     499         1643 :         } else if (mat->windowOpticalData == Window::OpticalDataModel::SpectralAverage) {
     500              : 
     501         1626 :             if (s_ipsc->rNumericArgs(2) + s_ipsc->rNumericArgs(3) > 1.0) {
     502            0 :                 ErrorsFound = true;
     503            0 :                 ShowSevereCustom(state, eoh, format("{} + {} not <= 1.0", s_ipsc->cNumericFieldNames(2), s_ipsc->cNumericFieldNames(3)));
     504              :             }
     505              : 
     506         1626 :             if (s_ipsc->rNumericArgs(2) + s_ipsc->rNumericArgs(4) > 1.0) {
     507            0 :                 ErrorsFound = true;
     508            0 :                 ShowSevereCustom(state, eoh, format("{} + {} not <= 1.0", s_ipsc->cNumericFieldNames(2), s_ipsc->cNumericFieldNames(4)));
     509              :             }
     510              : 
     511         1626 :             if (s_ipsc->rNumericArgs(5) + s_ipsc->rNumericArgs(6) > 1.0) {
     512            0 :                 ErrorsFound = true;
     513            0 :                 ShowSevereCustom(state, eoh, format("{} + {} not <= 1.0", s_ipsc->cNumericFieldNames(5), s_ipsc->cNumericFieldNames(6)));
     514              :             }
     515              : 
     516         1626 :             if (s_ipsc->rNumericArgs(5) + s_ipsc->rNumericArgs(7) > 1.0) {
     517            0 :                 ErrorsFound = true;
     518            0 :                 ShowSevereCustom(state, eoh, format("{} + {} not <= 1.0", s_ipsc->cNumericFieldNames(5), s_ipsc->cNumericFieldNames(7)));
     519              :             }
     520              : 
     521         1626 :             if (s_ipsc->rNumericArgs(8) + s_ipsc->rNumericArgs(9) > 1.0) {
     522            0 :                 ErrorsFound = true;
     523            0 :                 ShowSevereCustom(state, eoh, format("{} + {} not <= 1.0", s_ipsc->cNumericFieldNames(8), s_ipsc->cNumericFieldNames(9)));
     524              :             }
     525              : 
     526         1626 :             if (s_ipsc->rNumericArgs(8) + s_ipsc->rNumericArgs(10) > 1.0) {
     527            0 :                 ErrorsFound = true;
     528            0 :                 ShowSevereCustom(state, eoh, format("{} + {} not <= 1.0", s_ipsc->cNumericFieldNames(8), s_ipsc->cNumericFieldNames(10)));
     529              :             }
     530              : 
     531         1626 :             if (s_ipsc->rNumericArgs(2) < 0.0) {
     532            0 :                 ShowSevereCustom(state, eoh, format("{} not >= 0.0", s_ipsc->cNumericFieldNames(2)));
     533            0 :                 ErrorsFound = true;
     534              :             }
     535              : 
     536         1626 :             if (s_ipsc->rNumericArgs(2) > 1.0) {
     537            0 :                 ErrorsFound = true;
     538            0 :                 ShowSevereCustom(state, eoh, format("{} not <= 1.0", s_ipsc->cNumericFieldNames(2)));
     539              :             }
     540              : 
     541         1626 :             if (s_ipsc->rNumericArgs(3) < 0.0 || s_ipsc->rNumericArgs(3) > 1.0) {
     542            0 :                 ErrorsFound = true;
     543            0 :                 ShowSevereCustom(state, eoh, format("{} not >= 0.0 and <= 1.0", s_ipsc->cNumericFieldNames(3)));
     544              :             }
     545              : 
     546         1626 :             if (s_ipsc->rNumericArgs(4) < 0.0 || s_ipsc->rNumericArgs(4) > 1.0) {
     547            0 :                 ErrorsFound = true;
     548            0 :                 ShowSevereCustom(state, eoh, format("{} not >= 0.0 and <= 1.0", s_ipsc->cNumericFieldNames(4)));
     549              :             }
     550              : 
     551         1626 :             if (s_ipsc->rNumericArgs(5) < 0.0) {
     552            0 :                 ShowWarningCustom(state, eoh, format("{} not >= 0.0", s_ipsc->cNumericFieldNames(5)));
     553              :             }
     554              : 
     555         1626 :             if (s_ipsc->rNumericArgs(5) > 1.0) {
     556            0 :                 ErrorsFound = true;
     557            0 :                 ShowSevereCustom(state, eoh, format("{} not <= 1.0", s_ipsc->cNumericFieldNames(5)));
     558              :             }
     559              : 
     560         1626 :             if (s_ipsc->rNumericArgs(6) < 0.0 || s_ipsc->rNumericArgs(6) > 1.0) {
     561            0 :                 ErrorsFound = true;
     562            0 :                 ShowSevereCustom(state, eoh, format("{} not >= 0.0 and <= 1.0", s_ipsc->cNumericFieldNames(6)));
     563              :             }
     564              : 
     565         1626 :             if (s_ipsc->rNumericArgs(7) < 0.0 || s_ipsc->rNumericArgs(7) > 1.0) {
     566            0 :                 ErrorsFound = true;
     567            0 :                 ShowSevereCustom(state, eoh, format("{} not >= 0.0 and <= 1.0", s_ipsc->cNumericFieldNames(7)));
     568              :             }
     569              :         }
     570              : 
     571         1726 :         if (s_ipsc->rNumericArgs(8) > 1.0) {
     572            0 :             ErrorsFound = true;
     573            0 :             ShowSevereCustom(state, eoh, format("{} not <= 1.0", s_ipsc->cNumericFieldNames(8)));
     574              :         }
     575              : 
     576         1726 :         if (s_ipsc->rNumericArgs(9) <= 0.0 || s_ipsc->rNumericArgs(9) >= 1.0) {
     577            0 :             ErrorsFound = true;
     578            0 :             ShowSevereCustom(state, eoh, format("{} not > 0.0 and < 1.0", s_ipsc->cNumericFieldNames(9)));
     579              :         }
     580              : 
     581         1726 :         if (s_ipsc->rNumericArgs(10) <= 0.0 || s_ipsc->rNumericArgs(10) >= 1.0) {
     582            0 :             ErrorsFound = true;
     583            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     584            0 :             ShowContinueError(state, format("{} not > 0.0 and < 1.0", s_ipsc->cNumericFieldNames(10)));
     585              :         }
     586              : 
     587         1726 :         if (s_ipsc->rNumericArgs(11) <= 0.0) {
     588            0 :             ErrorsFound = true;
     589            0 :             ShowSevereCustom(state, eoh, format("{} not > 0.0", s_ipsc->cNumericFieldNames(11)));
     590              :         }
     591              : 
     592         1726 :         if (s_ipsc->rNumericArgs(13) < 0.0) {
     593            0 :             ErrorsFound = true;
     594            0 :             ShowSevereCustom(state, eoh, format("{} not > 0.0", s_ipsc->cNumericFieldNames(13)));
     595              :         }
     596              : 
     597         1726 :         if (s_ipsc->rNumericArgs(14) < 0.0 || s_ipsc->rNumericArgs(14) >= 1.0) {
     598            0 :             ErrorsFound = true;
     599            0 :             ShowSevereCustom(state, eoh, format("{} not > 0.0 and < 1.0", s_ipsc->cNumericFieldNames(14)));
     600              :         }
     601              : 
     602         1726 :         if (s_ipsc->cAlphaArgs(4) == "") {
     603            0 :             mat->SolarDiffusing = false;
     604              :         } else {
     605         1726 :             BooleanSwitch answer = getYesNoValue(s_ipsc->cAlphaArgs(4));
     606         1726 :             if (answer == BooleanSwitch::Invalid) {
     607            0 :                 ErrorsFound = true;
     608            0 :                 ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     609            0 :                 ShowContinueError(state, format("{} must be Yes or No, entered value={}", s_ipsc->cNumericFieldNames(4), s_ipsc->cAlphaArgs(4)));
     610              :             } else {
     611         1726 :                 mat->SolarDiffusing = (answer == BooleanSwitch::Yes);
     612              :             }
     613              :         }
     614              : 
     615              :         // Get SpectralAndAngle table names
     616         1726 :         if (mat->windowOpticalData == Window::OpticalDataModel::SpectralAndAngle) {
     617            1 :             if (s_ipsc->lAlphaFieldBlanks(5)) {
     618            0 :                 ErrorsFound = true;
     619            0 :                 ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaFieldNames(2), "SpectralAndAngle");
     620            1 :             } else if ((mat->GlassSpecAngTransCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(5))) == nullptr) {
     621            0 :                 ErrorsFound = true;
     622            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5));
     623            1 :             } else if (mat->GlassSpecAngTransCurve->numDims != 2) {
     624            0 :                 Curve::ShowSevereCurveDims(state, eoh, s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5), "2", mat->GlassSpecAngTransCurve->numDims);
     625            0 :                 ErrorsFound = true;
     626              :             } else {
     627            1 :                 Real64 minAng = mat->GlassSpecAngTransCurve->inputLimits[0].min;
     628            1 :                 Real64 maxAng = mat->GlassSpecAngTransCurve->inputLimits[0].max;
     629            1 :                 Real64 minLam = mat->GlassSpecAngTransCurve->inputLimits[1].min;
     630            1 :                 Real64 maxLam = mat->GlassSpecAngTransCurve->inputLimits[1].max;
     631              : 
     632            1 :                 if (minAng > 1.0e-6) {
     633            0 :                     ErrorsFound = true;
     634            0 :                     ShowSevereCustom(state,
     635              :                                      eoh,
     636            0 :                                      format("{} requires the minimum value = 0.0 in the entered table name={}",
     637            0 :                                             s_ipsc->cAlphaFieldNames(5),
     638            0 :                                             s_ipsc->cAlphaArgs(5)));
     639              :                 }
     640              : 
     641            1 :                 if (std::abs(maxAng - 90.0) > 1.0e-6) {
     642            0 :                     ErrorsFound = true;
     643            0 :                     ShowSevereCustom(state,
     644              :                                      eoh,
     645            0 :                                      format("{} requires the maximum value = 90.0 in the entered table name={}",
     646            0 :                                             s_ipsc->cAlphaFieldNames(5),
     647            0 :                                             s_ipsc->cAlphaArgs(5)));
     648              :                 }
     649              : 
     650            1 :                 if (minLam < 0.1) {
     651            0 :                     ErrorsFound = true;
     652            0 :                     ShowSevereCustom(state,
     653              :                                      eoh,
     654            0 :                                      format("{} requires the minumum value = 0.1 micron in the entered table name={}",
     655            0 :                                             s_ipsc->cAlphaFieldNames(5),
     656            0 :                                             s_ipsc->cAlphaArgs(5)));
     657              :                 }
     658              : 
     659            1 :                 if (maxLam > 4.0) {
     660            0 :                     ErrorsFound = true;
     661            0 :                     ShowSevereCustom(state,
     662              :                                      eoh,
     663            0 :                                      format("{} requires the maximum value = 4.0 microns in the entered table name={}",
     664            0 :                                             s_ipsc->cAlphaFieldNames(5),
     665            0 :                                             s_ipsc->cAlphaArgs(5)));
     666              :                 }
     667              :             }
     668              : 
     669            1 :             if (s_ipsc->lAlphaFieldBlanks(6)) {
     670            0 :                 ErrorsFound = true;
     671            0 :                 ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaFieldNames(2), "SpectralAndAngle");
     672            1 :             } else if ((mat->GlassSpecAngFReflCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(6))) == nullptr) {
     673            0 :                 ErrorsFound = true;
     674            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaArgs(6));
     675            1 :             } else if (mat->GlassSpecAngFReflCurve->numDims != 2) {
     676            0 :                 Curve::ShowSevereCurveDims(state, eoh, s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaArgs(6), "2", mat->GlassSpecAngFReflCurve->numDims);
     677            0 :                 ErrorsFound = true;
     678              :             } else {
     679            1 :                 Real64 minAng = mat->GlassSpecAngFReflCurve->inputLimits[0].min;
     680            1 :                 Real64 maxAng = mat->GlassSpecAngFReflCurve->inputLimits[0].max;
     681            1 :                 Real64 minLam = mat->GlassSpecAngFReflCurve->inputLimits[1].min;
     682            1 :                 Real64 maxLam = mat->GlassSpecAngFReflCurve->inputLimits[1].max;
     683            1 :                 if (minAng > 1.0e-6) {
     684            0 :                     ErrorsFound = true;
     685            0 :                     ShowSevereCustom(state,
     686              :                                      eoh,
     687            0 :                                      format("{} requires the minumum value = 0.0 in the entered table name={}",
     688            0 :                                             s_ipsc->cAlphaFieldNames(5),
     689            0 :                                             s_ipsc->cAlphaArgs(5)));
     690              :                 }
     691            1 :                 if (std::abs(maxAng - 90.0) > 1.0e-6) {
     692            0 :                     ErrorsFound = true;
     693            0 :                     ShowSevereCustom(state,
     694              :                                      eoh,
     695            0 :                                      format("{} requires the maximum value = 90.0 in the entered table name={}",
     696            0 :                                             s_ipsc->cAlphaFieldNames(5),
     697            0 :                                             s_ipsc->cAlphaArgs(5)));
     698              :                 }
     699            1 :                 if (minLam < 0.1) {
     700            0 :                     ErrorsFound = true;
     701            0 :                     ShowSevereCustom(state,
     702              :                                      eoh,
     703            0 :                                      format("{} requires the minumum value = 0.1 micron in the entered table name={}",
     704            0 :                                             s_ipsc->cAlphaFieldNames(5),
     705            0 :                                             s_ipsc->cAlphaArgs(5)));
     706              :                 }
     707            1 :                 if (maxLam > 4.0) {
     708            0 :                     ErrorsFound = true;
     709            0 :                     ShowSevereCustom(state,
     710              :                                      eoh,
     711            0 :                                      format("{} requires the maximum value = 4.0 microns in the entered table name={}",
     712            0 :                                             s_ipsc->cAlphaFieldNames(5),
     713            0 :                                             s_ipsc->cAlphaArgs(5)));
     714              :                 }
     715              :             }
     716              : 
     717            1 :             if (s_ipsc->lAlphaFieldBlanks(7)) {
     718            0 :                 ErrorsFound = true;
     719            0 :                 ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(7), s_ipsc->cAlphaFieldNames(2), "SpectralAndAngle");
     720            1 :             } else if ((mat->GlassSpecAngBReflCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(7))) == nullptr) {
     721            0 :                 ErrorsFound = true;
     722            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(7), s_ipsc->cAlphaArgs(7));
     723            1 :             } else if (mat->GlassSpecAngBReflCurve->numDims != 2) {
     724            0 :                 Curve::ShowSevereCurveDims(state, eoh, s_ipsc->cAlphaFieldNames(7), s_ipsc->cAlphaArgs(7), "2", mat->GlassSpecAngBReflCurve->numDims);
     725            0 :                 ErrorsFound = true;
     726              :             } else {
     727            1 :                 Real64 minAng = mat->GlassSpecAngFReflCurve->inputLimits[0].min;
     728            1 :                 Real64 maxAng = mat->GlassSpecAngFReflCurve->inputLimits[0].max;
     729            1 :                 Real64 minLam = mat->GlassSpecAngFReflCurve->inputLimits[1].min;
     730            1 :                 Real64 maxLam = mat->GlassSpecAngFReflCurve->inputLimits[1].max;
     731            1 :                 if (minAng > 1.0e-6) {
     732            0 :                     ErrorsFound = true;
     733            0 :                     ShowSevereCustom(state,
     734              :                                      eoh,
     735            0 :                                      format("{} requires the minumum value = 0.0 in the entered table name={}",
     736            0 :                                             s_ipsc->cAlphaFieldNames(5),
     737            0 :                                             s_ipsc->cAlphaArgs(5)));
     738              :                 }
     739            1 :                 if (std::abs(maxAng - 90.0) > 1.0e-6) {
     740            0 :                     ErrorsFound = true;
     741            0 :                     ShowSevereCustom(state,
     742              :                                      eoh,
     743            0 :                                      format("{} requires the maximum value = 90.0 in the entered table name={}",
     744            0 :                                             s_ipsc->cAlphaFieldNames(5),
     745            0 :                                             s_ipsc->cAlphaArgs(5)));
     746              :                 }
     747            1 :                 if (minLam < 0.1) {
     748            0 :                     ErrorsFound = true;
     749            0 :                     ShowSevereCustom(state,
     750              :                                      eoh,
     751            0 :                                      format("{} requires the minumum value = 0.1 micron in the entered table name={}",
     752            0 :                                             s_ipsc->cAlphaFieldNames(5),
     753            0 :                                             s_ipsc->cAlphaArgs(5)));
     754              :                 }
     755            1 :                 if (maxLam > 4.0) {
     756            0 :                     ErrorsFound = true;
     757            0 :                     ShowSevereCustom(state,
     758              :                                      eoh,
     759            0 :                                      format("{} requires the maximum value = 4.0 microns in the entered table name={}",
     760            0 :                                             s_ipsc->cAlphaFieldNames(5),
     761            0 :                                             s_ipsc->cAlphaArgs(5)));
     762              :                 }
     763              :             }
     764              :         }
     765              :     }
     766              : 
     767              :     // Glass materials, alternative input: index of refraction and extinction coefficient
     768              : 
     769          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Glazing:RefractionExtinctionMethod";
     770          801 :     s_mat->NumW5AltGlazings = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     771          811 :     for (int Loop = 1; Loop <= s_mat->NumW5AltGlazings; ++Loop) {
     772              : 
     773              :         // Call Input Get routine to retrieve material data
     774           20 :         s_ip->getObjectItem(state,
     775           10 :                             s_ipsc->cCurrentModuleObject,
     776              :                             Loop,
     777           10 :                             s_ipsc->cAlphaArgs,
     778              :                             NumAlphas,
     779           10 :                             s_ipsc->rNumericArgs,
     780              :                             NumNums,
     781              :                             IOStat,
     782           10 :                             s_ipsc->lNumericFieldBlanks,
     783           10 :                             s_ipsc->lAlphaFieldBlanks,
     784           10 :                             s_ipsc->cAlphaFieldNames,
     785           10 :                             s_ipsc->cNumericFieldNames);
     786              : 
     787           10 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     788              : 
     789           10 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     790            0 :             ShowSevereDuplicateName(state, eoh);
     791            0 :             ErrorsFound = true;
     792            0 :             continue;
     793              :         }
     794              : 
     795           10 :         auto *mat = new MaterialGlass;
     796           10 :         mat->group = Group::Glass;
     797           10 :         mat->Name = s_ipsc->cAlphaArgs(1);
     798              : 
     799           10 :         s_mat->materials.push_back(mat);
     800           10 :         mat->Num = s_mat->materials.isize();
     801           10 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
     802              : 
     803           10 :         mat->Roughness = SurfaceRoughness::VerySmooth;
     804           10 :         mat->Thickness = s_ipsc->rNumericArgs(1);
     805           10 :         mat->ROnly = true;
     806              : 
     807              :         // Calculate solar and visible transmittance and reflectance at normal incidence from thickness,
     808              :         // index of refraction and extinction coefficient. With the alternative input the front and back
     809              :         // properties are assumed to be the same.
     810              : 
     811           10 :         ReflectivitySol = pow_2((s_ipsc->rNumericArgs(2) - 1.0) / (s_ipsc->rNumericArgs(2) + 1.0));
     812           10 :         ReflectivityVis = pow_2((s_ipsc->rNumericArgs(4) - 1.0) / (s_ipsc->rNumericArgs(4) + 1.0));
     813           10 :         TransmittivitySol = std::exp(-s_ipsc->rNumericArgs(3) * s_ipsc->rNumericArgs(1));
     814           10 :         TransmittivityVis = std::exp(-s_ipsc->rNumericArgs(5) * s_ipsc->rNumericArgs(1));
     815           10 :         mat->Trans = TransmittivitySol * pow_2(1.0 - ReflectivitySol) / (1.0 - pow_2(ReflectivitySol * TransmittivitySol));
     816           10 :         mat->ReflectSolBeamFront =
     817           10 :             ReflectivitySol * (1.0 + pow_2(1.0 - ReflectivitySol) * pow_2(TransmittivitySol) / (1.0 - pow_2(ReflectivitySol * TransmittivitySol)));
     818           10 :         mat->ReflectSolBeamBack = mat->ReflectSolBeamFront;
     819           10 :         mat->TransVis = TransmittivityVis * pow_2(1.0 - ReflectivityVis) / (1.0 - pow_2(ReflectivityVis * TransmittivityVis));
     820              : 
     821           10 :         mat->ReflectVisBeamFront =
     822           10 :             ReflectivityVis * (1.0 + pow_2(1.0 - ReflectivityVis) * pow_2(TransmittivityVis) / (1.0 - pow_2(ReflectivityVis * TransmittivityVis)));
     823           10 :         mat->ReflectVisBeamBack = mat->ReflectSolBeamFront;
     824           10 :         mat->TransThermal = s_ipsc->rNumericArgs(6);
     825           10 :         mat->AbsorpThermalFront = s_ipsc->rNumericArgs(7);
     826           10 :         mat->AbsorpThermalBack = s_ipsc->rNumericArgs(7);
     827           10 :         mat->Conductivity = s_ipsc->rNumericArgs(8);
     828           10 :         mat->GlassTransDirtFactor = s_ipsc->rNumericArgs(9);
     829           10 :         if (s_ipsc->rNumericArgs(9) == 0.0) {
     830            0 :             mat->GlassTransDirtFactor = 1.0;
     831              :         }
     832           10 :         mat->AbsorpThermal = mat->AbsorpThermalBack;
     833              : 
     834           10 :         if (mat->Conductivity > 0.0) {
     835           10 :             mat->Resistance = mat->NominalR = mat->Thickness / mat->Conductivity;
     836              :         }
     837              : 
     838           10 :         mat->GlassSpectralDataPtr = 0;
     839              : 
     840           10 :         if (s_ipsc->rNumericArgs(6) + s_ipsc->rNumericArgs(7) >= 1.0) {
     841            0 :             ErrorsFound = true;
     842            0 :             ShowSevereCustom(state, eoh, format("{} + {} not < 1.0", s_ipsc->cNumericFieldNames(6), s_ipsc->cNumericFieldNames(7)));
     843              :         }
     844              : 
     845           10 :         if (s_ipsc->cAlphaArgs(2) == "") {
     846            0 :             mat->SolarDiffusing = false;
     847           10 :         } else if (s_ipsc->cAlphaArgs(2) == "YES") {
     848            0 :             mat->SolarDiffusing = true;
     849           10 :         } else if (s_ipsc->cAlphaArgs(2) == "NO") {
     850           10 :             mat->SolarDiffusing = false;
     851              :         } else {
     852            0 :             ErrorsFound = true;
     853            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     854            0 :             ShowContinueError(state, format("{} must be Yes or No, entered value={}", s_ipsc->cNumericFieldNames(2), s_ipsc->cAlphaArgs(4)));
     855              :         }
     856              :     }
     857              : 
     858              :     // Glass materials, equivalent layer (ASHWAT) method
     859          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Glazing:EquivalentLayer";
     860          801 :     s_mat->NumEQLGlazings = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     861          805 :     for (int Loop = 1; Loop <= s_mat->NumEQLGlazings; ++Loop) {
     862              : 
     863              :         // Call Input Get routine to retrieve material data
     864            8 :         s_ip->getObjectItem(state,
     865            4 :                             s_ipsc->cCurrentModuleObject,
     866              :                             Loop,
     867            4 :                             s_ipsc->cAlphaArgs,
     868              :                             NumAlphas,
     869            4 :                             s_ipsc->rNumericArgs,
     870              :                             NumNums,
     871              :                             IOStat,
     872            4 :                             s_ipsc->lNumericFieldBlanks,
     873            4 :                             s_ipsc->lAlphaFieldBlanks,
     874            4 :                             s_ipsc->cAlphaFieldNames,
     875            4 :                             s_ipsc->cNumericFieldNames);
     876              : 
     877            4 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     878              : 
     879            4 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     880            0 :             ShowSevereDuplicateName(state, eoh);
     881            0 :             ErrorsFound = true;
     882            0 :             continue;
     883              :         }
     884              : 
     885            4 :         auto *mat = new MaterialGlassEQL;
     886            4 :         mat->group = Group::GlassEQL;
     887            4 :         mat->Name = s_ipsc->cAlphaArgs(1);
     888              : 
     889            4 :         s_mat->materials.push_back(mat);
     890            4 :         mat->Num = s_mat->materials.isize();
     891            4 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
     892              : 
     893            4 :         mat->Roughness = SurfaceRoughness::VerySmooth;
     894            4 :         mat->ROnly = true;
     895              : 
     896            4 :         mat->TAR.Sol.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
     897            4 :         mat->TAR.Sol.Bk.Bm[0].BmTra = s_ipsc->rNumericArgs(2);
     898            4 :         mat->TAR.Sol.Ft.Bm[0].BmRef = s_ipsc->rNumericArgs(3);
     899            4 :         mat->TAR.Sol.Bk.Bm[0].BmRef = s_ipsc->rNumericArgs(4);
     900            4 :         mat->TAR.Vis.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(5);
     901            4 :         mat->TAR.Vis.Bk.Bm[0].BmTra = s_ipsc->rNumericArgs(6);
     902            4 :         mat->TAR.Vis.Ft.Bm[0].BmRef = s_ipsc->rNumericArgs(7);
     903            4 :         mat->TAR.Vis.Bk.Bm[0].BmRef = s_ipsc->rNumericArgs(8);
     904            4 :         mat->TAR.Sol.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(9);
     905            4 :         mat->TAR.Sol.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(10);
     906            4 :         mat->TAR.Sol.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(11);
     907            4 :         mat->TAR.Sol.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(12);
     908            4 :         mat->TAR.Vis.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(13);
     909            4 :         mat->TAR.Vis.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(14);
     910            4 :         mat->TAR.Vis.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(15);
     911            4 :         mat->TAR.Vis.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(16);
     912            4 :         mat->TAR.Sol.Ft.Df.Tra = mat->TAR.Sol.Bk.Df.Tra = s_ipsc->rNumericArgs(17);
     913            4 :         mat->TAR.Sol.Ft.Df.Ref = s_ipsc->rNumericArgs(18);
     914            4 :         mat->TAR.Sol.Bk.Df.Ref = s_ipsc->rNumericArgs(19);
     915            4 :         mat->TAR.Vis.Ft.Df.Tra = mat->TAR.Vis.Bk.Df.Tra = s_ipsc->rNumericArgs(20);
     916            4 :         mat->TAR.Vis.Ft.Df.Ref = s_ipsc->rNumericArgs(21);
     917            4 :         mat->TAR.Vis.Bk.Df.Ref = s_ipsc->rNumericArgs(22);
     918            4 :         mat->TAR.IR.Ft.Tra = mat->TAR.IR.Bk.Tra = s_ipsc->rNumericArgs(23);
     919            4 :         mat->TAR.IR.Ft.Emi = s_ipsc->rNumericArgs(24);
     920            4 :         mat->TAR.IR.Bk.Emi = s_ipsc->rNumericArgs(25);
     921            4 :         mat->Resistance = s_ipsc->rNumericArgs(26);
     922            4 :         if (mat->Resistance <= 0.0) {
     923            0 :             mat->Resistance = 0.158; // equivalent to single pane of 1/4" inch standard glass
     924              :         }
     925              :         // Assumes thermal emissivity is the same as thermal absorptance
     926            4 :         mat->AbsorpThermalFront = mat->TAR.IR.Ft.Tra;
     927            4 :         mat->AbsorpThermalBack = mat->TAR.IR.Bk.Tra;
     928            4 :         mat->TransThermal = mat->TAR.IR.Ft.Tra;
     929              : 
     930            4 :         mat->windowOpticalData = static_cast<Window::OpticalDataModel>(getEnumValue(Window::opticalDataModelNamesUC, s_ipsc->cAlphaArgs(2)));
     931              : 
     932              :         // IF(dataMaterial.Material(MaterNum)%GlassSpectralDataPtr == 0 .AND. Util::SameString(s_ipsc->cAlphaArgs(2),'Spectral')) THEN
     933              :         //  ErrorsFound = .TRUE.
     934              :         //  CALL ShowSevereError(state, TRIM(s_ipsc->cCurrentModuleObject)//'="'//Trim(dataMaterial.Material(MaterNum)%Name)// &
     935              :         //        '" has '//TRIM(cAlphaFieldNames(2))//' = Spectral but has no matching MaterialProperty:GlazingSpectralData set')
     936              :         //  if (s_ipsc->lAlphaFieldBlanks(3)) THEN
     937              :         //    CALL ShowContinueError(state, '...'//TRIM(cAlphaFieldNames(3))//' is blank.')
     938              :         //  ELSE
     939              :         //    CALL ShowContinueError(state, '...'//TRIM(cAlphaFieldNames(3))//'="'//TRIM(s_ipsc->cAlphaArgs(3))//  &
     940              :         //       '" not found as item in MaterialProperty:GlazingSpectralData objects.')
     941              :         //  END IF
     942              :         // END IF
     943              : 
     944            4 :         if (mat->windowOpticalData != Window::OpticalDataModel::SpectralAverage) {
     945            0 :             ErrorsFound = true;
     946            0 :             ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2), "Must be \"SpectralAverage\".");
     947              :         }
     948              : 
     949              :     } // W5GlsMatEQL loop
     950              : 
     951              :     // Window gas materials (for gaps with a single gas)
     952              : 
     953          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Gas";
     954          801 :     s_mat->NumW5Gases = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     955         1618 :     for (int Loop = 1; Loop <= s_mat->NumW5Gases; ++Loop) {
     956              : 
     957              :         // Call Input Get routine to retrieve material data
     958         1634 :         s_ip->getObjectItem(state,
     959          817 :                             s_ipsc->cCurrentModuleObject,
     960              :                             Loop,
     961          817 :                             s_ipsc->cAlphaArgs,
     962              :                             NumAlphas,
     963          817 :                             s_ipsc->rNumericArgs,
     964              :                             NumNums,
     965              :                             IOStat,
     966          817 :                             s_ipsc->lNumericFieldBlanks,
     967          817 :                             s_ipsc->lAlphaFieldBlanks,
     968          817 :                             s_ipsc->cAlphaFieldNames,
     969          817 :                             s_ipsc->cNumericFieldNames);
     970              : 
     971          817 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     972              : 
     973          817 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
     974            0 :             ShowSevereDuplicateName(state, eoh);
     975            0 :             ErrorsFound = true;
     976            0 :             continue;
     977              :         }
     978              : 
     979          817 :         auto *matGas = new MaterialGasMix;
     980          817 :         matGas->group = Group::Gas;
     981          817 :         matGas->Name = s_ipsc->cAlphaArgs(1);
     982              : 
     983          817 :         s_mat->materials.push_back(matGas);
     984          817 :         matGas->Num = s_mat->materials.isize();
     985          817 :         s_mat->materialMap.insert_or_assign(matGas->Name, matGas->Num);
     986              : 
     987          817 :         matGas->numGases = 1;
     988          817 :         matGas->gasFracts[0] = 1.0;
     989              : 
     990              :         // Load the material derived type from the input data.
     991              : 
     992          817 :         matGas->gases[0].type = static_cast<GasType>(getEnumValue(gasTypeNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(2))));
     993          817 :         matGas->Roughness = SurfaceRoughness::MediumRough;
     994              : 
     995          817 :         matGas->Thickness = s_ipsc->rNumericArgs(1);
     996          817 :         matGas->ROnly = true;
     997              : 
     998          817 :         gasType = matGas->gases[0].type;
     999          817 :         if (gasType != GasType::Custom) {
    1000          815 :             matGas->gases[0] = gases[(int)gasType];
    1001              :         }
    1002              : 
    1003              :         // Custom gas
    1004              : 
    1005          817 :         if (gasType == GasType::Custom) {
    1006            2 :             matGas->gases[0].con.c0 = s_ipsc->rNumericArgs(2);
    1007            2 :             matGas->gases[0].con.c1 = s_ipsc->rNumericArgs(3);
    1008            2 :             matGas->gases[0].con.c2 = s_ipsc->rNumericArgs(4);
    1009            2 :             matGas->gases[0].vis.c0 = s_ipsc->rNumericArgs(5);
    1010            2 :             matGas->gases[0].vis.c1 = s_ipsc->rNumericArgs(6);
    1011            2 :             matGas->gases[0].vis.c2 = s_ipsc->rNumericArgs(7);
    1012            2 :             matGas->gases[0].cp.c0 = s_ipsc->rNumericArgs(8);
    1013            2 :             matGas->gases[0].cp.c1 = s_ipsc->rNumericArgs(9);
    1014            2 :             matGas->gases[0].cp.c2 = s_ipsc->rNumericArgs(10);
    1015            2 :             matGas->gases[0].wght = s_ipsc->rNumericArgs(11);
    1016            2 :             matGas->gases[0].specHeatRatio = s_ipsc->rNumericArgs(12);
    1017              : 
    1018              :             // Check for errors in custom gas properties
    1019              :             //      IF(dataMaterial.Material(MaterNum)%GasCon(1,1) <= 0.0) THEN
    1020              :             //        ErrorsFound = .TRUE.
    1021              :             //        CALL ShowSevereError(state, 'Conductivity Coefficient A for custom window gas='&
    1022              :             //                 //TRIM(s_ipsc->cAlphaArgs(1))//' should be > 0.')
    1023              :             //      END IF
    1024              : 
    1025            2 :             if (matGas->gases[0].vis.c0 <= 0.0) {
    1026            0 :                 ErrorsFound = true;
    1027            0 :                 ShowSevereCustom(state, eoh, format("{} not > 0.0", s_ipsc->cNumericFieldNames(5)));
    1028              :             }
    1029            2 :             if (matGas->gases[0].cp.c0 <= 0.0) {
    1030            0 :                 ErrorsFound = true;
    1031            0 :                 ShowSevereCustom(state, eoh, format("{} not > 0.0", s_ipsc->cNumericFieldNames(8)));
    1032              :             }
    1033            2 :             if (matGas->gases[0].wght <= 0.0) {
    1034            0 :                 ErrorsFound = true;
    1035            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1036            0 :                 ShowContinueError(state, s_ipsc->cNumericFieldNames(11) + " not > 0.0");
    1037              :             }
    1038              :         }
    1039              : 
    1040              :         // Nominal resistance of gap at room temperature
    1041          817 :         if (!ErrorsFound) {
    1042          817 :             DenomRGas = (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
    1043          817 :             if (DenomRGas > 0.0) {
    1044          817 :                 matGas->NominalR = matGas->Thickness / DenomRGas;
    1045              :             } else {
    1046            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1047            0 :                 ShowContinueError(state,
    1048            0 :                                   format("Nominal resistance of gap at room temperature calculated at a negative Conductivity=[{:.3R}].", DenomRGas));
    1049            0 :                 ErrorsFound = true;
    1050              :             }
    1051              :         }
    1052              :     }
    1053              : 
    1054              :     // Window gap materials (for gaps with a single gas for EquivalentLayer)
    1055              : 
    1056          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Gap:EquivalentLayer";
    1057          801 :     s_mat->NumEQLGaps = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1058          809 :     for (int Loop = 1; Loop <= s_mat->NumEQLGaps; ++Loop) {
    1059              : 
    1060              :         // Call Input Get routine to retrieve material data
    1061           16 :         s_ip->getObjectItem(state,
    1062            8 :                             s_ipsc->cCurrentModuleObject,
    1063              :                             Loop,
    1064            8 :                             s_ipsc->cAlphaArgs,
    1065              :                             NumAlphas,
    1066            8 :                             s_ipsc->rNumericArgs,
    1067              :                             NumNums,
    1068              :                             IOStat,
    1069            8 :                             s_ipsc->lNumericFieldBlanks,
    1070            8 :                             s_ipsc->lAlphaFieldBlanks,
    1071            8 :                             s_ipsc->cAlphaFieldNames,
    1072            8 :                             s_ipsc->cNumericFieldNames);
    1073              : 
    1074            8 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1075              : 
    1076            8 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1077            0 :             ShowSevereDuplicateName(state, eoh);
    1078            0 :             ErrorsFound = true;
    1079            0 :             continue;
    1080              :         }
    1081              : 
    1082            8 :         auto *matGas = new MaterialGasMix;
    1083            8 :         matGas->group = Group::WindowGapEQL;
    1084            8 :         matGas->Name = s_ipsc->cAlphaArgs(1);
    1085              : 
    1086            8 :         s_mat->materials.push_back(matGas);
    1087            8 :         matGas->Num = s_mat->materials.isize();
    1088            8 :         s_mat->materialMap.insert_or_assign(matGas->Name, matGas->Num);
    1089              : 
    1090            8 :         matGas->numGases = 1;
    1091            8 :         matGas->gasFracts[0] = 1.0;
    1092              : 
    1093              :         // Load the material derived type from the input data.
    1094              : 
    1095            8 :         matGas->gases[0].type = static_cast<GasType>(getEnumValue(gasTypeNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(2)))); // Error check?
    1096              : 
    1097            8 :         matGas->Roughness = SurfaceRoughness::MediumRough;
    1098              : 
    1099            8 :         matGas->Thickness = s_ipsc->rNumericArgs(1);
    1100            8 :         matGas->ROnly = true;
    1101              : 
    1102            8 :         gasType = matGas->gases[0].type;
    1103            8 :         if (gasType != GasType::Custom) {
    1104            8 :             matGas->gases[0] = gases[(int)gasType];
    1105              :         }
    1106              : 
    1107            8 :         if (!s_ipsc->lAlphaFieldBlanks(2)) {
    1108              :             // Get gap vent type
    1109            8 :             matGas->gapVentType = static_cast<GapVentType>(getEnumValue(gapVentTypeNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(3))));
    1110              :         }
    1111              : 
    1112            8 :         if (gasType == GasType::Custom) {
    1113            0 :             for (ICoeff = 1; ICoeff <= 3; ++ICoeff) {
    1114            0 :                 matGas->gases[0].con.c0 = s_ipsc->rNumericArgs(2);
    1115            0 :                 matGas->gases[0].con.c1 = s_ipsc->rNumericArgs(3);
    1116            0 :                 matGas->gases[0].con.c2 = s_ipsc->rNumericArgs(4);
    1117            0 :                 matGas->gases[0].vis.c0 = s_ipsc->rNumericArgs(5);
    1118            0 :                 matGas->gases[0].vis.c1 = s_ipsc->rNumericArgs(6);
    1119            0 :                 matGas->gases[0].vis.c2 = s_ipsc->rNumericArgs(7);
    1120            0 :                 matGas->gases[0].cp.c0 = s_ipsc->rNumericArgs(8);
    1121            0 :                 matGas->gases[0].cp.c1 = s_ipsc->rNumericArgs(9);
    1122            0 :                 matGas->gases[0].cp.c2 = s_ipsc->rNumericArgs(10);
    1123              :             }
    1124            0 :             matGas->gases[0].wght = s_ipsc->rNumericArgs(11);
    1125            0 :             matGas->gases[0].specHeatRatio = s_ipsc->rNumericArgs(12);
    1126              : 
    1127            0 :             if (matGas->gases[0].vis.c0 <= 0.0) {
    1128            0 :                 ErrorsFound = true;
    1129            0 :                 ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1130            0 :                 ShowContinueError(state, format("{} not > 0.0", s_ipsc->cNumericFieldNames(5)));
    1131              :             }
    1132            0 :             if (matGas->gases[0].cp.c0 <= 0.0) {
    1133            0 :                 ErrorsFound = true;
    1134            0 :                 ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1135            0 :                 ShowContinueError(state, format("{} not > 0.0", s_ipsc->cNumericFieldNames(8)));
    1136              :             }
    1137            0 :             if (matGas->gases[0].wght <= 0.0) {
    1138            0 :                 ErrorsFound = true;
    1139            0 :                 ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1140            0 :                 ShowContinueError(state, format("{} not > 0.0", s_ipsc->cNumericFieldNames(11)));
    1141              :             }
    1142              :         }
    1143              : 
    1144              :         // Nominal resistance of gap at room temperature
    1145            8 :         if (!ErrorsFound) {
    1146            8 :             DenomRGas = (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
    1147            8 :             if (DenomRGas > 0.0) {
    1148            8 :                 matGas->NominalR = matGas->Thickness / DenomRGas;
    1149              :             } else {
    1150            0 :                 ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1151            0 :                 ShowContinueError(state,
    1152            0 :                                   format("Nominal resistance of gap at room temperature calculated at a negative Conductivity=[{:.3R}].", DenomRGas));
    1153            0 :                 ErrorsFound = true;
    1154              :             }
    1155              :         }
    1156              :     } // for (Loop : W5MatEQL)
    1157              : 
    1158              :     // Window gas mixtures (for gaps with two or more gases)
    1159              : 
    1160          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:GasMixture";
    1161          801 :     s_mat->NumW5GasMixtures = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1162          817 :     for (int Loop = 1; Loop <= s_mat->NumW5GasMixtures; ++Loop) {
    1163              : 
    1164              :         // Call Input Get routine to retrieve material data
    1165           32 :         s_ip->getObjectItem(state,
    1166           16 :                             s_ipsc->cCurrentModuleObject,
    1167              :                             Loop,
    1168           16 :                             s_ipsc->cAlphaArgs,
    1169              :                             NumAlphas,
    1170           16 :                             s_ipsc->rNumericArgs,
    1171              :                             NumNums,
    1172              :                             IOStat,
    1173           16 :                             s_ipsc->lNumericFieldBlanks,
    1174           16 :                             s_ipsc->lAlphaFieldBlanks,
    1175           16 :                             s_ipsc->cAlphaFieldNames,
    1176           16 :                             s_ipsc->cNumericFieldNames);
    1177           16 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1178              : 
    1179           16 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1180            0 :             ShowSevereDuplicateName(state, eoh);
    1181            0 :             ErrorsFound = true;
    1182            0 :             continue;
    1183              :         }
    1184              : 
    1185           16 :         auto *matGas = new MaterialGasMix;
    1186           16 :         matGas->group = Group::GasMixture;
    1187           16 :         matGas->Name = s_ipsc->cAlphaArgs(1);
    1188              : 
    1189           16 :         s_mat->materials.push_back(matGas);
    1190           16 :         matGas->Num = s_mat->materials.isize();
    1191           16 :         s_mat->materialMap.insert_or_assign(matGas->Name, matGas->Num);
    1192              : 
    1193           16 :         matGas->gases[0].type = matGas->gases[1].type = matGas->gases[2].type = matGas->gases[3].type = matGas->gases[4].type = GasType::Invalid;
    1194              : 
    1195              :         // Load the material derived type from the input data.
    1196              : 
    1197           16 :         NumGases = s_ipsc->rNumericArgs(2);
    1198           16 :         matGas->numGases = NumGases;
    1199           48 :         for (NumGas = 0; NumGas < NumGases; ++NumGas) {
    1200           32 :             auto &gas = matGas->gases[NumGas];
    1201           32 :             gas.type = static_cast<GasType>(getEnumValue(gasTypeNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(2 + NumGas))));
    1202           32 :             if (gas.type == GasType::Invalid) {
    1203            0 :                 ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1 + NumGas)));
    1204              :                 // Error check?
    1205            0 :                 ErrorsFound = true;
    1206              :             }
    1207              :         }
    1208              : 
    1209           16 :         matGas->Roughness = SurfaceRoughness::MediumRough; // Unused
    1210              : 
    1211           16 :         matGas->Thickness = s_ipsc->rNumericArgs(1);
    1212           16 :         if (matGas->Thickness <= 0.0) {
    1213            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1214            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(1) + " must be greater than 0.");
    1215              :         }
    1216           16 :         matGas->ROnly = true;
    1217              : 
    1218           48 :         for (NumGas = 0; NumGas < NumGases; ++NumGas) {
    1219           32 :             gasType = matGas->gases[NumGas].type;
    1220           32 :             if (gasType != GasType::Custom) {
    1221           32 :                 matGas->gasFracts[NumGas] = s_ipsc->rNumericArgs(3 + NumGas);
    1222           32 :                 matGas->gases[NumGas] = gases[(int)gasType];
    1223              :             }
    1224              :         }
    1225              : 
    1226              :         // Nominal resistance of gap at room temperature (based on first gas in mixture)
    1227           16 :         matGas->NominalR = matGas->Thickness / (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
    1228              :     }
    1229              : 
    1230              :     // Window Shade Materials
    1231              : 
    1232          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Shade";
    1233          801 :     s_mat->NumShades = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1234          818 :     for (int Loop = 1; Loop <= s_mat->NumShades; ++Loop) {
    1235              : 
    1236              :         // Call Input Get routine to retrieve material data
    1237           34 :         s_ip->getObjectItem(state,
    1238           17 :                             s_ipsc->cCurrentModuleObject,
    1239              :                             Loop,
    1240           17 :                             s_ipsc->cAlphaArgs,
    1241              :                             NumAlphas,
    1242           17 :                             s_ipsc->rNumericArgs,
    1243              :                             NumNums,
    1244              :                             IOStat,
    1245           17 :                             s_ipsc->lNumericFieldBlanks,
    1246           17 :                             s_ipsc->lAlphaFieldBlanks,
    1247           17 :                             s_ipsc->cAlphaFieldNames,
    1248           17 :                             s_ipsc->cNumericFieldNames);
    1249              : 
    1250           17 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1251              : 
    1252           17 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1253            0 :             ShowSevereDuplicateName(state, eoh);
    1254            0 :             ErrorsFound = true;
    1255            0 :             continue;
    1256              :         }
    1257              : 
    1258           17 :         auto *mat = new MaterialShade;
    1259           17 :         mat->Name = s_ipsc->cAlphaArgs(1);
    1260              : 
    1261           17 :         s_mat->materials.push_back(mat);
    1262           17 :         mat->Num = s_mat->materials.isize();
    1263           17 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    1264              : 
    1265           17 :         mat->Roughness = SurfaceRoughness::MediumRough;
    1266           17 :         mat->Trans = s_ipsc->rNumericArgs(1);
    1267           17 :         mat->ReflectShade = s_ipsc->rNumericArgs(2);
    1268           17 :         mat->TransVis = s_ipsc->rNumericArgs(3);
    1269           17 :         mat->ReflectShadeVis = s_ipsc->rNumericArgs(4);
    1270           17 :         mat->AbsorpThermal = s_ipsc->rNumericArgs(5);
    1271           17 :         mat->AbsorpThermalInput = s_ipsc->rNumericArgs(5);
    1272           17 :         mat->TransThermal = s_ipsc->rNumericArgs(6);
    1273           17 :         mat->Thickness = s_ipsc->rNumericArgs(7);
    1274           17 :         mat->Conductivity = s_ipsc->rNumericArgs(8);
    1275           17 :         mat->AbsorpSolar = max(0.0, 1.0 - mat->Trans - mat->ReflectShade);
    1276           17 :         mat->AbsorpSolarInput = mat->AbsorpSolar;
    1277           17 :         mat->toGlassDist = s_ipsc->rNumericArgs(9);
    1278           17 :         mat->topOpeningMult = s_ipsc->rNumericArgs(10);
    1279           17 :         mat->bottomOpeningMult = s_ipsc->rNumericArgs(11);
    1280           17 :         mat->leftOpeningMult = s_ipsc->rNumericArgs(12);
    1281           17 :         mat->rightOpeningMult = s_ipsc->rNumericArgs(13);
    1282           17 :         mat->airFlowPermeability = s_ipsc->rNumericArgs(14);
    1283           17 :         mat->ROnly = true;
    1284              : 
    1285           17 :         if (mat->Conductivity > 0.0) {
    1286           17 :             mat->NominalR = mat->Thickness / mat->Conductivity;
    1287              :         } else {
    1288            0 :             mat->NominalR = 1.0;
    1289              :         }
    1290              : 
    1291           17 :         if (s_ipsc->rNumericArgs(1) + s_ipsc->rNumericArgs(2) >= 1.0) {
    1292            0 :             ErrorsFound = true;
    1293            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1294            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(1) + " + " + s_ipsc->cNumericFieldNames(2) + " not < 1.0");
    1295              :         }
    1296              : 
    1297           17 :         if (s_ipsc->rNumericArgs(3) + s_ipsc->rNumericArgs(4) >= 1.0) {
    1298            0 :             ErrorsFound = true;
    1299            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1300            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(3) + " + " + s_ipsc->cNumericFieldNames(4) + " not < 1.0");
    1301              :         }
    1302              : 
    1303           17 :         if (s_ipsc->rNumericArgs(5) + s_ipsc->rNumericArgs(6) >= 1.0) {
    1304            0 :             ErrorsFound = true;
    1305            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1306            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(5) + " + " + s_ipsc->cNumericFieldNames(6) + " not < 1.0");
    1307              :         }
    1308              :     }
    1309              : 
    1310              :     // Window Shade Materials
    1311              : 
    1312          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Shade:EquivalentLayer";
    1313          801 :     s_mat->NumEQLShades = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1314          803 :     for (int Loop = 1; Loop <= s_mat->NumEQLShades; ++Loop) {
    1315              : 
    1316            2 :         s_ipsc->rNumericArgs = 0;
    1317              : 
    1318              :         // Call Input Get routine to retrieve material data
    1319            4 :         s_ip->getObjectItem(state,
    1320            2 :                             s_ipsc->cCurrentModuleObject,
    1321              :                             Loop,
    1322            2 :                             s_ipsc->cAlphaArgs,
    1323              :                             NumAlphas,
    1324            2 :                             s_ipsc->rNumericArgs,
    1325              :                             NumNums,
    1326              :                             IOStat,
    1327            2 :                             s_ipsc->lNumericFieldBlanks,
    1328            2 :                             s_ipsc->lAlphaFieldBlanks,
    1329            2 :                             s_ipsc->cAlphaFieldNames,
    1330            2 :                             s_ipsc->cNumericFieldNames);
    1331              : 
    1332            2 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1333              : 
    1334            2 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1335            0 :             ShowSevereDuplicateName(state, eoh);
    1336            0 :             ErrorsFound = true;
    1337            0 :             continue;
    1338              :         }
    1339              : 
    1340            2 :         auto *mat = new MaterialShadeEQL;
    1341            2 :         mat->group = Group::ShadeEQL;
    1342            2 :         mat->Name = s_ipsc->cAlphaArgs(1);
    1343              : 
    1344            2 :         s_mat->materials.push_back(mat);
    1345            2 :         mat->Num = s_mat->materials.isize();
    1346            2 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    1347              : 
    1348            2 :         mat->Roughness = SurfaceRoughness::MediumRough;
    1349            2 :         mat->ROnly = true;
    1350              : 
    1351              :         //  Front side and back side have the same beam-Beam Transmittance
    1352            2 :         mat->TAR.Sol.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
    1353            2 :         mat->TAR.Sol.Bk.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
    1354            2 :         mat->TAR.Sol.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(2);
    1355            2 :         mat->TAR.Sol.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(3);
    1356            2 :         mat->TAR.Sol.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(4);
    1357            2 :         mat->TAR.Sol.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(5);
    1358            2 :         mat->TAR.Vis.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(6);
    1359            2 :         mat->TAR.Vis.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(7);
    1360            2 :         mat->TAR.Vis.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(8);
    1361            2 :         mat->TAR.IR.Ft.Tra = mat->TAR.IR.Bk.Tra = s_ipsc->rNumericArgs(9);
    1362            2 :         mat->TAR.IR.Ft.Emi = s_ipsc->rNumericArgs(10);
    1363            2 :         mat->TAR.IR.Bk.Emi = s_ipsc->rNumericArgs(11);
    1364              :         // Assumes thermal emissivity is the same as thermal absorptance
    1365            2 :         mat->AbsorpThermalFront = mat->TAR.IR.Ft.Emi;
    1366            2 :         mat->AbsorpThermalBack = mat->TAR.IR.Bk.Emi;
    1367            2 :         mat->TransThermal = mat->TAR.IR.Ft.Tra;
    1368              : 
    1369            2 :         if (s_ipsc->rNumericArgs(1) + s_ipsc->rNumericArgs(2) + s_ipsc->rNumericArgs(4) >= 1.0) {
    1370            0 :             ErrorsFound = true;
    1371            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1372            0 :             ShowContinueError(
    1373            0 :                 state, s_ipsc->cNumericFieldNames(1) + " + " + s_ipsc->cNumericFieldNames(2) + " + " + s_ipsc->cNumericFieldNames(4) + "not < 1.0");
    1374              :         }
    1375            2 :         if (s_ipsc->rNumericArgs(1) + s_ipsc->rNumericArgs(3) + s_ipsc->rNumericArgs(5) >= 1.0) {
    1376            0 :             ErrorsFound = true;
    1377            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1378            0 :             ShowContinueError(
    1379            0 :                 state, s_ipsc->cNumericFieldNames(1) + " + " + s_ipsc->cNumericFieldNames(3) + " + " + s_ipsc->cNumericFieldNames(5) + "not < 1.0");
    1380              :         }
    1381            2 :         if (s_ipsc->rNumericArgs(6) + s_ipsc->rNumericArgs(7) + s_ipsc->rNumericArgs(8) >= 1.0) {
    1382            0 :             ErrorsFound = true;
    1383            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1384            0 :             ShowContinueError(
    1385            0 :                 state, s_ipsc->cNumericFieldNames(6) + " + " + s_ipsc->cNumericFieldNames(7) + " + " + s_ipsc->cNumericFieldNames(8) + "not < 1.0");
    1386              :         }
    1387            2 :         if (s_ipsc->rNumericArgs(9) + s_ipsc->rNumericArgs(10) >= 1.0) {
    1388            0 :             ErrorsFound = true;
    1389            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1390            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " + " + s_ipsc->cNumericFieldNames(10) + " not < 1.0");
    1391              :         }
    1392            2 :         if (s_ipsc->rNumericArgs(9) + s_ipsc->rNumericArgs(11) >= 1.0) {
    1393            0 :             ErrorsFound = true;
    1394            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1395            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " + " + s_ipsc->cNumericFieldNames(11) + " not < 1.0");
    1396              :         }
    1397              : 
    1398              :     } // TotShadesEQL loop
    1399              : 
    1400              :     // Window drape materials
    1401              : 
    1402          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Drape:EquivalentLayer";
    1403          801 :     s_mat->NumEQLDrapes = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1404          801 :     for (int Loop = 1; Loop <= s_mat->NumEQLDrapes; ++Loop) {
    1405              : 
    1406            0 :         s_ipsc->rNumericArgs = 0;
    1407              : 
    1408              :         // Call Input Get routine to retrieve material data
    1409            0 :         s_ip->getObjectItem(state,
    1410            0 :                             s_ipsc->cCurrentModuleObject,
    1411              :                             Loop,
    1412            0 :                             s_ipsc->cAlphaArgs,
    1413              :                             NumAlphas,
    1414            0 :                             s_ipsc->rNumericArgs,
    1415              :                             NumNums,
    1416              :                             IOStat,
    1417            0 :                             s_ipsc->lNumericFieldBlanks,
    1418            0 :                             s_ipsc->lAlphaFieldBlanks,
    1419            0 :                             s_ipsc->cAlphaFieldNames,
    1420            0 :                             s_ipsc->cNumericFieldNames);
    1421              : 
    1422            0 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1423              : 
    1424            0 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1425            0 :             ShowSevereDuplicateName(state, eoh);
    1426            0 :             ErrorsFound = true;
    1427            0 :             continue;
    1428              :         }
    1429              : 
    1430            0 :         auto *mat = new MaterialDrapeEQL;
    1431            0 :         mat->group = Group::DrapeEQL;
    1432            0 :         mat->Name = s_ipsc->cAlphaArgs(1);
    1433              : 
    1434            0 :         s_mat->materials.push_back(mat);
    1435            0 :         mat->Num = s_mat->materials.isize();
    1436            0 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    1437              : 
    1438            0 :         mat->Roughness = SurfaceRoughness::MediumRough;
    1439            0 :         mat->ROnly = true;
    1440              : 
    1441              :         //  Front side and back side have the same properties
    1442            0 :         mat->TAR.Sol.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
    1443            0 :         mat->TAR.Sol.Bk.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
    1444              : 
    1445            0 :         mat->TAR.Sol.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(2);
    1446            0 :         mat->TAR.Sol.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(3);
    1447              : 
    1448            0 :         mat->TAR.Sol.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(4);
    1449            0 :         mat->TAR.Sol.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(5);
    1450            0 :         mat->TAR.Vis.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(6);
    1451            0 :         mat->TAR.Vis.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(7);
    1452            0 :         mat->TAR.Vis.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(8);
    1453            0 :         mat->TAR.IR.Ft.Tra = mat->TAR.IR.Bk.Tra = s_ipsc->rNumericArgs(9);
    1454            0 :         mat->TAR.IR.Ft.Emi = s_ipsc->rNumericArgs(10);
    1455            0 :         mat->TAR.IR.Bk.Emi = s_ipsc->rNumericArgs(11);
    1456              :         // Assumes thermal emissivity is the same as thermal absorptance
    1457            0 :         mat->AbsorpThermalFront = mat->TAR.IR.Ft.Emi;
    1458            0 :         mat->AbsorpThermalBack = mat->TAR.IR.Bk.Emi;
    1459            0 :         mat->TransThermal = mat->TAR.IR.Ft.Tra;
    1460              : 
    1461            0 :         if (!s_ipsc->lNumericFieldBlanks(12) && !s_ipsc->lNumericFieldBlanks(13)) {
    1462            0 :             if (s_ipsc->rNumericArgs(12) != 0.0 && s_ipsc->rNumericArgs(13) != 0.0) {
    1463            0 :                 mat->pleatedWidth = s_ipsc->rNumericArgs(12);
    1464            0 :                 mat->pleatedLength = s_ipsc->rNumericArgs(13);
    1465            0 :                 mat->isPleated = true;
    1466              :             }
    1467              :         } else {
    1468            0 :             mat->isPleated = false;
    1469              :         }
    1470            0 :         if (s_ipsc->rNumericArgs(1) + s_ipsc->rNumericArgs(2) + s_ipsc->rNumericArgs(4) >= 1.0) {
    1471            0 :             ErrorsFound = true;
    1472            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1473            0 :             ShowContinueError(
    1474            0 :                 state, s_ipsc->cNumericFieldNames(1) + " + " + s_ipsc->cNumericFieldNames(2) + " + " + s_ipsc->cNumericFieldNames(4) + "not < 1.0");
    1475              :         }
    1476            0 :         if (s_ipsc->rNumericArgs(6) + s_ipsc->rNumericArgs(7) + s_ipsc->rNumericArgs(8) >= 1.0) {
    1477            0 :             ErrorsFound = true;
    1478            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1479            0 :             ShowContinueError(
    1480            0 :                 state, s_ipsc->cNumericFieldNames(4) + " + " + s_ipsc->cNumericFieldNames(5) + " + " + s_ipsc->cNumericFieldNames(6) + "not < 1.0");
    1481              :         }
    1482            0 :         if (s_ipsc->rNumericArgs(9) + s_ipsc->rNumericArgs(10) > 1.0) {
    1483            0 :             ErrorsFound = true;
    1484            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1485            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " + " + s_ipsc->cNumericFieldNames(10) + " not < 1.0");
    1486              :         }
    1487              : 
    1488              :     } // TotDrapesEQL loop
    1489              : 
    1490              :     // Window Screen Materials
    1491              : 
    1492          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Screen";
    1493          801 :     s_mat->NumScreens = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1494          803 :     for (int Loop = 1; Loop <= s_mat->NumScreens; ++Loop) {
    1495              : 
    1496              :         // Call GetObjectItem routine to retrieve material data
    1497            4 :         s_ip->getObjectItem(state,
    1498            2 :                             s_ipsc->cCurrentModuleObject,
    1499              :                             Loop,
    1500            2 :                             s_ipsc->cAlphaArgs,
    1501              :                             NumAlphas,
    1502            2 :                             s_ipsc->rNumericArgs,
    1503              :                             NumNums,
    1504              :                             IOStat,
    1505            2 :                             s_ipsc->lNumericFieldBlanks,
    1506            2 :                             s_ipsc->lAlphaFieldBlanks,
    1507            2 :                             s_ipsc->cAlphaFieldNames,
    1508            2 :                             s_ipsc->cNumericFieldNames);
    1509              : 
    1510            2 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1511              : 
    1512            2 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1513            0 :             ShowSevereDuplicateName(state, eoh);
    1514            0 :             ErrorsFound = true;
    1515            0 :             continue;
    1516              :         }
    1517              : 
    1518            2 :         auto *matScreen = new MaterialScreen;
    1519            2 :         matScreen->Name = s_ipsc->cAlphaArgs(1);
    1520              : 
    1521            2 :         s_mat->materials.push_back(matScreen);
    1522            2 :         matScreen->Num = s_mat->materials.isize();
    1523            2 :         s_mat->materialMap.insert_or_assign(matScreen->Name, matScreen->Num);
    1524              : 
    1525              :         // Load the material derived type from the input data.
    1526              : 
    1527            2 :         matScreen->bmRefModel =
    1528            2 :             static_cast<ScreenBeamReflectanceModel>(getEnumValue(screenBeamReflectanceModelNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(2))));
    1529            2 :         if (matScreen->bmRefModel == ScreenBeamReflectanceModel::Invalid) {
    1530            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1531            0 :             ShowContinueError(state,
    1532            0 :                               format("{}=\"{}\", must be one of DoNotModel, ModelAsDirectBeam or ModelAsDiffuse.",
    1533            0 :                                      s_ipsc->cAlphaFieldNames(2),
    1534            0 :                                      s_ipsc->cAlphaArgs(2)));
    1535            0 :             ErrorsFound = true;
    1536              :         }
    1537            2 :         matScreen->Roughness = SurfaceRoughness::MediumRough;
    1538            2 :         matScreen->ShadeRef = s_ipsc->rNumericArgs(1);
    1539            2 :         if (matScreen->ShadeRef < 0.0 || matScreen->ShadeRef > 1.0) {
    1540            0 :             ErrorsFound = true;
    1541            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1542            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(1) + " must be >= 0 and <= 1");
    1543              :         }
    1544            2 :         matScreen->ShadeRefVis = s_ipsc->rNumericArgs(2);
    1545            2 :         if (matScreen->ShadeRefVis < 0.0 || matScreen->ShadeRefVis > 1.0) {
    1546            0 :             ErrorsFound = true;
    1547            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1548            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(2) + " must be >= 0 and <= 1 for material " + matScreen->Name + '.');
    1549              :         }
    1550            2 :         matScreen->AbsorpThermal = s_ipsc->rNumericArgs(3);
    1551            2 :         matScreen->AbsorpThermalInput = s_ipsc->rNumericArgs(3);
    1552            2 :         if (matScreen->AbsorpThermal < 0.0 || matScreen->AbsorpThermal > 1.0) {
    1553            0 :             ErrorsFound = true;
    1554            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1555            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(3) + " must be >= 0 and <= 1");
    1556              :         }
    1557            2 :         matScreen->Conductivity = s_ipsc->rNumericArgs(4);
    1558            2 :         matScreen->Thickness = s_ipsc->rNumericArgs(6); // thickness = diameter
    1559              : 
    1560            2 :         if (s_ipsc->rNumericArgs(5) > 0.0) {
    1561              :             //      Screens(ScNum)%ScreenDiameterToSpacingRatio = s_ipsc->rNumericArgs(6)/s_ipsc->rNumericArgs(5) or
    1562              :             //      1-SQRT(dataMaterial.Material(MaterNum)%Trans
    1563            2 :             if (s_ipsc->rNumericArgs(6) / s_ipsc->rNumericArgs(5) >= 1.0) {
    1564            0 :                 ErrorsFound = true;
    1565            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1566            0 :                 ShowContinueError(state, s_ipsc->cNumericFieldNames(6) + " must be less than " + s_ipsc->cNumericFieldNames(5));
    1567              :             } else {
    1568              :                 //       Calculate direct normal transmittance (open area fraction)
    1569            2 :                 matScreen->Trans = pow_2(1.0 - s_ipsc->rNumericArgs(6) / s_ipsc->rNumericArgs(5));
    1570              :             }
    1571              :         } else {
    1572            0 :             ErrorsFound = true;
    1573            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1574            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(5) + " must be > 0.");
    1575            0 :             s_ipsc->rNumericArgs(5) = 0.000000001;
    1576              :         }
    1577              : 
    1578            2 :         if (s_ipsc->rNumericArgs(6) <= 0.0) {
    1579            0 :             ErrorsFound = true;
    1580            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1581            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(6) + " must be > 0.");
    1582              :         }
    1583              : 
    1584              :         //   Modify reflectance to account for the open area in the screen assembly
    1585            2 :         matScreen->ShadeRef *= (1.0 - matScreen->Trans);
    1586            2 :         matScreen->ShadeRefVis *= (1.0 - matScreen->Trans);
    1587              : 
    1588            2 :         matScreen->toGlassDist = s_ipsc->rNumericArgs(7);
    1589            2 :         if (matScreen->toGlassDist < 0.001 || matScreen->toGlassDist > 1.0) {
    1590            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1591            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(7) + " must be greater than or equal to 0.001 and less than or equal to 1.");
    1592              :         }
    1593              : 
    1594            2 :         matScreen->topOpeningMult = s_ipsc->rNumericArgs(8);
    1595            2 :         if (matScreen->topOpeningMult < 0.0 || matScreen->topOpeningMult > 1.0) {
    1596            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1597            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(8) + " must be greater than or equal to 0 and less than or equal to 1.");
    1598              :         }
    1599              : 
    1600            2 :         matScreen->bottomOpeningMult = s_ipsc->rNumericArgs(9);
    1601            2 :         if (matScreen->bottomOpeningMult < 0.0 || matScreen->bottomOpeningMult > 1.0) {
    1602            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1603            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " must be greater than or equal to 0 and less than or equal to 1.");
    1604              :         }
    1605              : 
    1606            2 :         matScreen->leftOpeningMult = s_ipsc->rNumericArgs(10);
    1607            2 :         if (matScreen->leftOpeningMult < 0.0 || matScreen->leftOpeningMult > 1.0) {
    1608            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1609            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(10) + " must be greater than or equal to 0 and less than or equal to 1.");
    1610              :         }
    1611              : 
    1612            2 :         matScreen->rightOpeningMult = s_ipsc->rNumericArgs(11);
    1613            2 :         if (matScreen->rightOpeningMult < 0.0 || matScreen->rightOpeningMult > 1.0) {
    1614            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1615            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(11) + " must be greater than or equal to 0 and less than or equal to 1.");
    1616              :         }
    1617              : 
    1618            2 :         matScreen->mapDegResolution = s_ipsc->rNumericArgs(12);
    1619            2 :         if (matScreen->mapDegResolution < 0 || matScreen->mapDegResolution > 5 || matScreen->mapDegResolution == 4) {
    1620            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1621            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(12) + " must be 0, 1, 2, 3, or 5.");
    1622            0 :             ErrorsFound = true;
    1623              :         }
    1624              : 
    1625              :         //   Default air flow permeability to open area fraction
    1626            2 :         matScreen->airFlowPermeability = matScreen->Trans;
    1627            2 :         matScreen->TransThermal = matScreen->Trans;
    1628            2 :         matScreen->TransVis = matScreen->Trans;
    1629              : 
    1630            2 :         matScreen->ROnly = true;
    1631              : 
    1632              :         //   Calculate absorptance accounting for the open area in the screen assembly (used only in CreateShadedWindowConstruction)
    1633            2 :         matScreen->AbsorpSolar = max(0.0, 1.0 - matScreen->Trans - matScreen->ShadeRef);
    1634            2 :         matScreen->AbsorpSolarInput = matScreen->AbsorpSolar;
    1635            2 :         matScreen->AbsorpVisible = max(0.0, 1.0 - matScreen->TransVis - matScreen->ShadeRefVis);
    1636            2 :         matScreen->AbsorpVisibleInput = matScreen->AbsorpVisible;
    1637            2 :         matScreen->AbsorpThermal *= (1.0 - matScreen->Trans);
    1638            2 :         matScreen->AbsorpThermalInput = matScreen->AbsorpThermal;
    1639              : 
    1640            2 :         if (matScreen->Conductivity > 0.0) {
    1641            2 :             matScreen->NominalR = (1.0 - matScreen->Trans) * matScreen->Thickness / matScreen->Conductivity;
    1642              :         } else {
    1643            0 :             matScreen->NominalR = 1.0;
    1644            0 :             ShowWarningError(
    1645              :                 state,
    1646            0 :                 "Conductivity for material=\"" + matScreen->Name +
    1647              :                     "\" must be greater than 0 for calculating Nominal R-value, Nominal R is defaulted to 1 and the simulation continues.");
    1648              :         }
    1649              : 
    1650            2 :         if (matScreen->Trans + matScreen->ShadeRef >= 1.0) {
    1651            0 :             ErrorsFound = true;
    1652            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1653            0 :             ShowContinueError(state, "Calculated solar transmittance + solar reflectance not < 1.0");
    1654            0 :             ShowContinueError(state, "See Engineering Reference for calculation procedure for solar transmittance.");
    1655              :         }
    1656              : 
    1657            2 :         if (matScreen->TransVis + matScreen->ShadeRefVis >= 1.0) {
    1658            0 :             ErrorsFound = true;
    1659            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1660            0 :             ShowContinueError(state, "Calculated visible transmittance + visible reflectance not < 1.0");
    1661            0 :             ShowContinueError(state, "See Engineering Reference for calculation procedure for visible solar transmittance.");
    1662              :         }
    1663              : 
    1664            2 :         if (matScreen->TransThermal + matScreen->AbsorpThermal >= 1.0) {
    1665            0 :             ErrorsFound = true;
    1666            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1667            0 :             ShowSevereError(state, "Thermal hemispherical emissivity plus open area fraction (1-diameter/spacing)**2 not < 1.0");
    1668              :         }
    1669              :     }
    1670              : 
    1671          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Screen:EquivalentLayer";
    1672          801 :     s_mat->NumEQLScreens = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1673          802 :     for (int Loop = 1; Loop <= s_mat->NumEQLScreens; ++Loop) {
    1674              : 
    1675            1 :         s_ipsc->rNumericArgs = 0;
    1676              : 
    1677              :         // Call GetObjectItem routine to retrieve material data
    1678            2 :         s_ip->getObjectItem(state,
    1679            1 :                             s_ipsc->cCurrentModuleObject,
    1680              :                             Loop,
    1681            1 :                             s_ipsc->cAlphaArgs,
    1682              :                             NumAlphas,
    1683            1 :                             s_ipsc->rNumericArgs,
    1684              :                             NumNums,
    1685              :                             IOStat,
    1686            1 :                             s_ipsc->lNumericFieldBlanks,
    1687            1 :                             s_ipsc->lAlphaFieldBlanks,
    1688            1 :                             s_ipsc->cAlphaFieldNames,
    1689            1 :                             s_ipsc->cNumericFieldNames);
    1690              : 
    1691            1 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1692              : 
    1693            1 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1694            0 :             ShowSevereDuplicateName(state, eoh);
    1695            0 :             ErrorsFound = true;
    1696            0 :             continue;
    1697              :         }
    1698              : 
    1699            1 :         auto *matScreen = new MaterialScreenEQL;
    1700            1 :         matScreen->group = Group::ScreenEQL;
    1701            1 :         matScreen->Name = s_ipsc->cAlphaArgs(1);
    1702              : 
    1703            1 :         s_mat->materials.push_back(matScreen);
    1704            1 :         matScreen->Num = s_mat->materials.isize();
    1705            1 :         s_mat->materialMap.insert_or_assign(matScreen->Name, matScreen->Num);
    1706              : 
    1707              :         // Load the material derived type from the input data.
    1708              :         // WindowMaterial:Screen:EquivalentLayer,
    1709            1 :         matScreen->Roughness = SurfaceRoughness::MediumRough;
    1710            1 :         matScreen->ROnly = true;
    1711            1 :         matScreen->TAR.Sol.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
    1712            1 :         matScreen->TAR.Sol.Bk.Bm[0].BmTra = s_ipsc->rNumericArgs(1);
    1713            1 :         matScreen->TAR.Sol.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(2);
    1714            1 :         matScreen->TAR.Sol.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(2);
    1715            1 :         matScreen->TAR.Sol.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(3);
    1716            1 :         matScreen->TAR.Sol.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(3);
    1717            1 :         matScreen->TAR.Vis.Ft.Bm[0].BmTra = s_ipsc->rNumericArgs(4);
    1718            1 :         matScreen->TAR.Vis.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(5);
    1719            1 :         matScreen->TAR.Vis.Ft.Df.Ref = s_ipsc->rNumericArgs(6);
    1720            1 :         matScreen->TAR.IR.Ft.Tra = matScreen->TAR.IR.Bk.Tra = s_ipsc->rNumericArgs(7);
    1721            1 :         matScreen->TAR.IR.Ft.Emi = s_ipsc->rNumericArgs(8);
    1722            1 :         matScreen->TAR.IR.Bk.Emi = s_ipsc->rNumericArgs(8);
    1723              : 
    1724              :         // Assumes thermal emissivity is the same as thermal absorptance
    1725            1 :         matScreen->AbsorpThermalFront = matScreen->TAR.IR.Ft.Emi;
    1726            1 :         matScreen->AbsorpThermalBack = matScreen->TAR.IR.Bk.Emi;
    1727            1 :         matScreen->TransThermal = matScreen->TAR.IR.Ft.Tra;
    1728              : 
    1729            1 :         if (s_ipsc->rNumericArgs(3) < 0.0 || s_ipsc->rNumericArgs(3) > 1.0) {
    1730            0 :             ErrorsFound = true;
    1731            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1732            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(3) + " must be >= 0 and <= 1");
    1733              :         }
    1734              : 
    1735            1 :         if (s_ipsc->rNumericArgs(6) < 0.0 || s_ipsc->rNumericArgs(6) > 1.0) {
    1736            0 :             ErrorsFound = true;
    1737            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1738            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(6) + " must be >= 0 and <= 1 for material " + matScreen->Name + '.');
    1739              :         }
    1740              : 
    1741            1 :         if (!s_ipsc->lNumericFieldBlanks(9)) {
    1742            1 :             if (s_ipsc->rNumericArgs(9) > 0.00001) {
    1743            1 :                 matScreen->wireSpacing = s_ipsc->rNumericArgs(9); // screen wire spacing
    1744              :             } else {
    1745            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1746            0 :                 ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " must be > 0.");
    1747            0 :                 ShowContinueError(state, "...Setting screen wire spacing to a default value of 0.025m and simulation continues.");
    1748            0 :                 matScreen->wireSpacing = 0.025;
    1749              :             }
    1750              :         }
    1751              : 
    1752            1 :         if (!s_ipsc->lNumericFieldBlanks(10)) {
    1753            1 :             if (s_ipsc->rNumericArgs(10) > 0.00001 && s_ipsc->rNumericArgs(10) < matScreen->wireSpacing) {
    1754            1 :                 matScreen->wireDiameter = s_ipsc->rNumericArgs(10); // screen wire spacing
    1755              :             } else {
    1756            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value.");
    1757            0 :                 ShowContinueError(state, s_ipsc->cNumericFieldNames(10) + " must be > 0.");
    1758            0 :                 ShowContinueError(state, "...Setting screen wire diameter to a default value of 0.005m and simulation continues.");
    1759            0 :                 matScreen->wireDiameter = 0.005;
    1760              :             }
    1761              :         }
    1762              : 
    1763            1 :         if (matScreen->wireSpacing > 0.0) {
    1764            1 :             if (matScreen->wireDiameter / matScreen->wireSpacing >= 1.0) {
    1765            0 :                 ErrorsFound = true;
    1766            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1767            0 :                 ShowContinueError(state, s_ipsc->cNumericFieldNames(10) + " must be less than " + s_ipsc->cNumericFieldNames(9));
    1768              :             } else {
    1769              :                 //  Calculate direct normal transmittance (open area fraction)
    1770            1 :                 Openness = pow_2(1.0 - matScreen->wireDiameter / matScreen->wireSpacing);
    1771            1 :                 if ((matScreen->TAR.Sol.Ft.Bm[0].BmTra - Openness) / Openness > 0.01) {
    1772            0 :                     ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", screen openness specified.");
    1773            0 :                     ShowContinueError(state, s_ipsc->cNumericFieldNames(1) + " is > 1.0% of the value calculated from input fields:");
    1774            0 :                     ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " and " + (s_ipsc->cNumericFieldNames(10)));
    1775            0 :                     ShowContinueError(state, " using the formula (1-diameter/spacing)**2");
    1776            0 :                     ShowContinueError(state, " ...the screen diameter is recalculated from the material openness specified ");
    1777            0 :                     ShowContinueError(state, " ...and wire spacing using the formula = wire spacing * (1.0 - SQRT(Opennes))");
    1778            0 :                     matScreen->wireDiameter = matScreen->wireSpacing * (1.0 - std::sqrt(matScreen->TAR.Sol.Ft.Bm[0].BmTra));
    1779            0 :                     ShowContinueError(state, format(" ...Recalculated {}={:.4R} m", s_ipsc->cNumericFieldNames(10), matScreen->wireDiameter));
    1780              :                 }
    1781              :             }
    1782              :         }
    1783              : 
    1784            1 :         if (matScreen->TAR.Sol.Ft.Bm[0].BmTra + matScreen->TAR.Sol.Ft.Bm[0].DfRef >= 1.0) {
    1785            0 :             ErrorsFound = true;
    1786            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1787            0 :             ShowContinueError(state, "Calculated solar transmittance + solar reflectance not < 1.0");
    1788            0 :             ShowContinueError(state, "See Engineering Reference for calculation procedure for solar transmittance.");
    1789              :         }
    1790              : 
    1791            1 :         if (matScreen->TAR.Vis.Ft.Bm[0].BmTra + matScreen->TAR.Vis.Ft.Df.Ref >= 1.0) {
    1792            0 :             ErrorsFound = true;
    1793            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1794            0 :             ShowContinueError(state, "Calculated visible transmittance + visible reflectance not < 1.0");
    1795            0 :             ShowContinueError(state, "See Engineering Reference for calculation procedure for visible solar transmittance.");
    1796              :         }
    1797            1 :         if (matScreen->TransThermal + matScreen->AbsorpThermal >= 1.0) {
    1798            0 :             ErrorsFound = true;
    1799            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1800            0 :             ShowSevereError(state, "Thermal hemispherical emissivity plus open area fraction (1-diameter/spacing)**2 not < 1.0");
    1801              :         }
    1802              : 
    1803              :     } // TotScreensEQL loop
    1804              : 
    1805          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Blind";
    1806          801 :     s_mat->NumBlinds = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1807          819 :     for (int Loop = 1; Loop <= s_mat->NumBlinds; ++Loop) {
    1808              : 
    1809              :         // Call Input Get routine to retrieve material data
    1810           36 :         s_ip->getObjectItem(state,
    1811           18 :                             s_ipsc->cCurrentModuleObject,
    1812              :                             Loop,
    1813           18 :                             s_ipsc->cAlphaArgs,
    1814              :                             NumAlphas,
    1815           18 :                             s_ipsc->rNumericArgs,
    1816              :                             NumNums,
    1817              :                             IOStat,
    1818           18 :                             s_ipsc->lNumericFieldBlanks,
    1819           18 :                             s_ipsc->lAlphaFieldBlanks,
    1820           18 :                             s_ipsc->cAlphaFieldNames,
    1821           18 :                             s_ipsc->cNumericFieldNames);
    1822              : 
    1823           18 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1824              : 
    1825           18 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    1826            0 :             ShowSevereDuplicateName(state, eoh);
    1827            0 :             ErrorsFound = true;
    1828            0 :             continue;
    1829              :         }
    1830              : 
    1831           18 :         auto *matBlind = new MaterialBlind;
    1832           18 :         matBlind->Name = s_ipsc->cAlphaArgs(1);
    1833              : 
    1834           18 :         s_mat->materials.push_back(matBlind);
    1835           18 :         matBlind->Num = s_mat->materials.isize();
    1836           18 :         s_mat->materialMap.insert_or_assign(matBlind->Name, matBlind->Num);
    1837              : 
    1838           18 :         matBlind->Roughness = SurfaceRoughness::Rough;
    1839           18 :         matBlind->ROnly = true;
    1840              : 
    1841           18 :         matBlind->SlatOrientation =
    1842           18 :             static_cast<DataWindowEquivalentLayer::Orientation>(getEnumValue(DataWindowEquivalentLayer::orientationNamesUC, s_ipsc->cAlphaArgs(2)));
    1843              : 
    1844           18 :         matBlind->SlatWidth = s_ipsc->rNumericArgs(1);
    1845           18 :         matBlind->SlatSeparation = s_ipsc->rNumericArgs(2);
    1846           18 :         matBlind->SlatThickness = s_ipsc->rNumericArgs(3);
    1847           18 :         matBlind->SlatAngle = s_ipsc->rNumericArgs(4);
    1848           18 :         matBlind->SlatConductivity = s_ipsc->rNumericArgs(5);
    1849              : 
    1850           18 :         matBlind->slatTAR.Sol.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(6);
    1851           18 :         matBlind->slatTAR.Sol.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(7);
    1852           18 :         matBlind->slatTAR.Sol.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(8);
    1853           18 :         matBlind->slatTAR.Sol.Ft.Df.Tra = s_ipsc->rNumericArgs(9);
    1854           18 :         matBlind->slatTAR.Sol.Ft.Df.Ref = s_ipsc->rNumericArgs(10);
    1855           18 :         matBlind->slatTAR.Sol.Bk.Df.Ref = s_ipsc->rNumericArgs(11);
    1856           18 :         matBlind->slatTAR.Vis.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(12);
    1857           18 :         matBlind->slatTAR.Vis.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(13);
    1858           18 :         matBlind->slatTAR.Vis.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(14);
    1859           18 :         matBlind->slatTAR.Vis.Ft.Df.Tra = s_ipsc->rNumericArgs(15);
    1860           18 :         matBlind->slatTAR.Vis.Ft.Df.Ref = s_ipsc->rNumericArgs(16);
    1861           18 :         matBlind->slatTAR.Vis.Bk.Df.Ref = s_ipsc->rNumericArgs(17);
    1862           18 :         matBlind->slatTAR.IR.Ft.Tra = matBlind->slatTAR.IR.Bk.Tra = s_ipsc->rNumericArgs(18);
    1863           18 :         matBlind->slatTAR.IR.Ft.Emi = s_ipsc->rNumericArgs(19);
    1864           18 :         matBlind->slatTAR.IR.Bk.Emi = s_ipsc->rNumericArgs(20);
    1865           18 :         matBlind->toGlassDist = s_ipsc->rNumericArgs(21);
    1866           18 :         matBlind->topOpeningMult = s_ipsc->rNumericArgs(22);
    1867           18 :         matBlind->bottomOpeningMult = s_ipsc->rNumericArgs(23);
    1868           18 :         matBlind->leftOpeningMult = s_ipsc->rNumericArgs(24);
    1869           18 :         matBlind->rightOpeningMult = s_ipsc->rNumericArgs(25);
    1870           18 :         matBlind->MinSlatAngle = s_ipsc->rNumericArgs(26);
    1871           18 :         matBlind->MaxSlatAngle = s_ipsc->rNumericArgs(27);
    1872              : 
    1873              :         // TH 2/11/2010. For CR 8010
    1874              :         // By default all blinds have fixed slat angle, new blinds with variable slat angle are created if
    1875              :         //  they are used with window shading controls that adjust slat angles like ScheduledSlatAngle or BlockBeamSolar
    1876           18 :         matBlind->SlatAngleType = DataWindowEquivalentLayer::AngleType::Fixed;
    1877              : 
    1878           18 :         if (matBlind->SlatWidth < matBlind->SlatSeparation) {
    1879            0 :             ShowWarningError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Slat Angles/Widths");
    1880            0 :             ShowContinueError(state,
    1881            0 :                               format("{} [{:.2R}] is less than {} [{:.2R}].",
    1882            0 :                                      s_ipsc->cNumericFieldNames(1),
    1883            0 :                                      matBlind->SlatWidth,
    1884            0 :                                      s_ipsc->cNumericFieldNames(2),
    1885            0 :                                      matBlind->SlatSeparation));
    1886            0 :             ShowContinueError(state, "This will allow direct beam to be transmitted when Slat angle = 0.");
    1887              :         }
    1888              : 
    1889           18 :         if ((s_ipsc->rNumericArgs(6) + s_ipsc->rNumericArgs(7) >= 1.0)) {
    1890            0 :             ErrorsFound = true;
    1891            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1892            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(6) + " + " + s_ipsc->cNumericFieldNames(7) + " not < 1.0");
    1893              :         }
    1894           18 :         if ((s_ipsc->rNumericArgs(6) + s_ipsc->rNumericArgs(8) >= 1.0)) {
    1895            0 :             ErrorsFound = true;
    1896            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1897            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(6) + " + " + s_ipsc->cNumericFieldNames(8) + " not < 1.0");
    1898              :         }
    1899              : 
    1900           18 :         if ((s_ipsc->rNumericArgs(9) + s_ipsc->rNumericArgs(10) >= 1.0)) {
    1901            0 :             ErrorsFound = true;
    1902            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1903            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " + " + s_ipsc->cNumericFieldNames(10) + " not < 1.0");
    1904              :         }
    1905           18 :         if ((s_ipsc->rNumericArgs(9) + s_ipsc->rNumericArgs(11) >= 1.0)) {
    1906            0 :             ErrorsFound = true;
    1907            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1908            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(9) + " + " + s_ipsc->cNumericFieldNames(11) + " not < 1.0");
    1909              :         }
    1910              : 
    1911           18 :         if ((s_ipsc->rNumericArgs(12) + s_ipsc->rNumericArgs(13) >= 1.0) || (s_ipsc->rNumericArgs(12) + s_ipsc->rNumericArgs(14) >= 1.0)) {
    1912            0 :             ErrorsFound = true;
    1913            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1914            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(12) + " + " + s_ipsc->cNumericFieldNames(13) + " not < 1.0 OR");
    1915            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(12) + " + " + s_ipsc->cNumericFieldNames(14) + " not < 1.0");
    1916              :         }
    1917              : 
    1918           18 :         if ((s_ipsc->rNumericArgs(12) + s_ipsc->rNumericArgs(13) >= 1.0)) {
    1919            0 :             ErrorsFound = true;
    1920            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1921            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(12) + " + " + s_ipsc->cNumericFieldNames(13) + " not < 1.0");
    1922              :         }
    1923           18 :         if ((s_ipsc->rNumericArgs(12) + s_ipsc->rNumericArgs(14) >= 1.0)) {
    1924            0 :             ErrorsFound = true;
    1925            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1926            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(12) + " + " + s_ipsc->cNumericFieldNames(14) + " not < 1.0");
    1927              :         }
    1928              : 
    1929           18 :         if ((s_ipsc->rNumericArgs(15) + s_ipsc->rNumericArgs(16) >= 1.0)) {
    1930            0 :             ErrorsFound = true;
    1931            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1932            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(15) + " + " + s_ipsc->cNumericFieldNames(16) + " not < 1.0");
    1933              :         }
    1934           18 :         if ((s_ipsc->rNumericArgs(15) + s_ipsc->rNumericArgs(17) >= 1.0)) {
    1935            0 :             ErrorsFound = true;
    1936            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1937            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(15) + " + " + s_ipsc->cNumericFieldNames(17) + " not < 1.0");
    1938              :         }
    1939              : 
    1940              :         // Require that beam and diffuse properties be the same
    1941           18 :         if (std::abs(s_ipsc->rNumericArgs(9) - s_ipsc->rNumericArgs(6)) > 1.e-5) {
    1942            0 :             ErrorsFound = true;
    1943            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1944            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(6) + " must equal " + s_ipsc->cNumericFieldNames(9));
    1945              :         }
    1946              : 
    1947           18 :         if (std::abs(s_ipsc->rNumericArgs(10) - s_ipsc->rNumericArgs(7)) > 1.e-5) {
    1948            0 :             ErrorsFound = true;
    1949            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1950            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(7) + " must equal " + s_ipsc->cNumericFieldNames(10));
    1951              :         }
    1952              : 
    1953           18 :         if (std::abs(s_ipsc->rNumericArgs(11) - s_ipsc->rNumericArgs(8)) > 1.e-5) {
    1954            0 :             ErrorsFound = true;
    1955            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1956            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(8) + " must equal " + s_ipsc->cNumericFieldNames(11));
    1957              :         }
    1958              : 
    1959           18 :         if (std::abs(s_ipsc->rNumericArgs(15) - s_ipsc->rNumericArgs(12)) > 1.e-5) {
    1960            0 :             ErrorsFound = true;
    1961            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1962            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(12) + " must equal " + s_ipsc->cNumericFieldNames(15));
    1963              :         }
    1964              : 
    1965           18 :         if (std::abs(s_ipsc->rNumericArgs(16) - s_ipsc->rNumericArgs(13)) > 1.e-5) {
    1966            0 :             ErrorsFound = true;
    1967            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1968            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(13) + " must equal " + s_ipsc->cNumericFieldNames(16));
    1969              :         }
    1970              : 
    1971           18 :         if (std::abs(s_ipsc->rNumericArgs(17) - s_ipsc->rNumericArgs(14)) > 1.e-5) {
    1972            0 :             ErrorsFound = true;
    1973            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1974            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(14) + " must equal " + s_ipsc->cNumericFieldNames(17));
    1975              :         }
    1976              : 
    1977           18 :         if ((s_ipsc->rNumericArgs(18) + s_ipsc->rNumericArgs(19) >= 1.0)) {
    1978            0 :             ErrorsFound = true;
    1979            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1980            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(18) + " + " + s_ipsc->cNumericFieldNames(19) + " not < 1.0");
    1981              :         }
    1982           18 :         if ((s_ipsc->rNumericArgs(18) + s_ipsc->rNumericArgs(20) >= 1.0)) {
    1983            0 :             ErrorsFound = true;
    1984            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1985            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(18) + " + " + s_ipsc->cNumericFieldNames(20) + " not < 1.0");
    1986              :         }
    1987              : 
    1988           18 :         if (matBlind->toGlassDist < 0.5 * matBlind->SlatWidth) {
    1989            0 :             ErrorsFound = true;
    1990            0 :             ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    1991            0 :             ShowContinueError(state, s_ipsc->cNumericFieldNames(21) + " is less than half of the " + s_ipsc->cNumericFieldNames(1));
    1992              :         }
    1993              : 
    1994              :         // Minimum and maximum slat angles allowed by slat geometry
    1995           18 :         if (matBlind->SlatWidth > matBlind->SlatSeparation) {
    1996           18 :             MinSlatAngGeom = std::asin(matBlind->SlatThickness / (matBlind->SlatThickness + matBlind->SlatSeparation)) / Constant::DegToRad;
    1997              :         } else {
    1998            0 :             MinSlatAngGeom = 0.0;
    1999              :         }
    2000           18 :         MaxSlatAngGeom = 180.0 - MinSlatAngGeom;
    2001              : 
    2002              :         // Error if input slat angle not in range allowed by slat geometry
    2003           18 :         if ((matBlind->SlatSeparation + matBlind->SlatThickness) < matBlind->SlatWidth) {
    2004           18 :             if (matBlind->SlatAngle < MinSlatAngGeom) {
    2005            0 :                 ErrorsFound = true;
    2006            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    2007            0 :                 ShowContinueError(state,
    2008            0 :                                   format("{}=[{:.1R}], is less than smallest allowed by slat dimensions and spacing, [{:.1R}] deg.",
    2009            0 :                                          s_ipsc->cNumericFieldNames(4),
    2010            0 :                                          matBlind->SlatAngle,
    2011              :                                          MinSlatAngGeom));
    2012           18 :             } else if (matBlind->SlatAngle > MaxSlatAngGeom) {
    2013            0 :                 ErrorsFound = true;
    2014            0 :                 ShowSevereError(state, s_ipsc->cCurrentModuleObject + "=\"" + s_ipsc->cAlphaArgs(1) + "\", Illegal value combination.");
    2015            0 :                 ShowContinueError(state,
    2016            0 :                                   format("{}=[{:.1R}], is greater than largest allowed by slat dimensions and spacing, [{:.1R}] deg.",
    2017            0 :                                          s_ipsc->cNumericFieldNames(4),
    2018            0 :                                          matBlind->SlatAngle,
    2019              :                                          MinSlatAngGeom));
    2020              :             }
    2021              :         }
    2022              : 
    2023              :         // By default all Blinds are "fixed" slats.  Only with Shading Control is one considered variable and this check
    2024              :         // is now done when that happens.  9.3.2009 LKL
    2025              : 
    2026              :         //    IF(Blind(Loop)%SlatAngleType == VariableSlats) THEN
    2027              :         //      ! Error if maximum slat angle less than minimum
    2028              :         //      IF(Blind(Loop)%MaxSlatAngle < Blind(Loop)%MinSlatAngle) THEN
    2029              :         //        ErrorsFound = .TRUE.
    2030              :         //        CALL ShowSevereError(state, TRIM(s_ipsc->cCurrentModuleObject)//'="'//TRIM(s_ipsc->cAlphaArgs(1))//'", Illegal value
    2031              :         //        combination.') CALL ShowContinueError(state,
    2032              :         //        TRIM(cNumericFieldNames(26))//'=['//TRIM(RoundSigDigits(Blind(Loop)%MinSlatAngle,1))//  &
    2033              :         //           '], is greater than '//TRIM(cNumericFieldNames(27))//'=['//  &
    2034              :         //           TRIM(RoundSigDigits(Blind(Loop)%MaxSlatAngle,1))//'] deg.')
    2035              :         //      END IF
    2036              :         //      ! Error if input slat angle not in input min/max range
    2037              :         //      IF(Blind(Loop)%MaxSlatAngle > Blind(Loop)%MinSlatAngle .AND. (Blind(Loop)%SlatAngle < Blind(Loop)%MinSlatAngle &
    2038              :         //          .OR. Blind(Loop)%SlatAngle > Blind(Loop)%MaxSlatAngle)) THEN
    2039              :         //        ErrorsFound = .TRUE.
    2040              :         //        CALL ShowSevereError(state, TRIM(s_ipsc->cCurrentModuleObject)//'="'//TRIM(s_ipsc->cAlphaArgs(1))//'", Illegal value
    2041              :         //        combination.') CALL ShowContinueError(state, TRIM(cNumericFieldNames(4))//'=['//TRIM(RoundSigDigits(Blind(Loop)%SlatAngle,1))//
    2042              :         //        &
    2043              :         //           '] is outside of the input min/max range, min=['//TRIM(RoundSigDigits(Blind(Loop)%MinSlatAngle,1))//  &
    2044              :         //           '], max=['//TRIM(RoundSigDigits(Blind(Loop)%MaxSlatAngle,1))//'] deg.')
    2045              :         //      END IF
    2046              :         //      ! Error if input minimum slat angle is less than that allowed by slat geometry
    2047              :         //      IF(Blind(Loop)%MinSlatAngle < MinSlatAngGeom) THEN
    2048              :         //        CALL ShowSevereError(state, TRIM(s_ipsc->cCurrentModuleObject)//'="'//TRIM(s_ipsc->cAlphaArgs(1))//'", Illegal value
    2049              :         //        combination.') CALL ShowContinueError(state,
    2050              :         //        TRIM(cNumericFieldNames(26))//'=['//TRIM(RoundSigDigits(Blind(Loop)%MinSlatAngle,1))//  &
    2051              :         //           '] is less than the smallest allowed by slat dimensions and spacing, min=['//  &
    2052              :         //           TRIM(RoundSigDigits(MinSlatAngGeom,1))//'] deg.')
    2053              :         //        CALL ShowContinueError(state, 'Minimum Slat Angle will be set to '//TRIM(RoundSigDigits(MinSlatAngGeom,1))//' deg.')
    2054              :         //        Blind(Loop)%MinSlatAngle = MinSlatAngGeom
    2055              :         //      END IF
    2056              :         //      ! Error if input maximum slat angle is greater than that allowed by slat geometry
    2057              :         //      IF(Blind(Loop)%MaxSlatAngle > MaxSlatAngGeom) THEN
    2058              :         //        CALL ShowWarningError(state, TRIM(s_ipsc->cCurrentModuleObject)//'="'//TRIM(s_ipsc->cAlphaArgs(1))//'", Illegal value
    2059              :         //        combination.') CALL ShowContinueError(state,
    2060              :         //        TRIM(cNumericFieldNames(27))//'=['//TRIM(RoundSigDigits(Blind(Loop)%MaxSlatAngle,1))//  &
    2061              :         //           '] is greater than the largest allowed by slat dimensions and spacing, ['//  &
    2062              :         //           TRIM(RoundSigDigits(MaxSlatAngGeom,1))//'] deg.')
    2063              :         //        CALL ShowContinueError(state, 'Maximum Slat Angle will be set to '//TRIM(RoundSigDigits(MaxSlatAngGeom,1))//' deg.')
    2064              :         //        Blind(Loop)%MaxSlatAngle = MaxSlatAngGeom
    2065              :         //      END IF
    2066              :         //    END IF  ! End of check if slat angle is variable
    2067              :     }
    2068              : 
    2069              :     // Window Blind Materials for EquivalentLayer Model
    2070              : 
    2071          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Blind:EquivalentLayer";
    2072          801 :     s_mat->NumEQLBlinds = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2073          801 :     for (int Loop = 1; Loop <= s_mat->NumEQLBlinds; ++Loop) {
    2074              : 
    2075              :         // Call Input Get routine to retrieve material data
    2076            0 :         s_ip->getObjectItem(state,
    2077            0 :                             s_ipsc->cCurrentModuleObject,
    2078              :                             Loop,
    2079            0 :                             s_ipsc->cAlphaArgs,
    2080              :                             NumAlphas,
    2081            0 :                             s_ipsc->rNumericArgs,
    2082              :                             NumNums,
    2083              :                             IOStat,
    2084            0 :                             s_ipsc->lNumericFieldBlanks,
    2085            0 :                             s_ipsc->lAlphaFieldBlanks,
    2086            0 :                             s_ipsc->cAlphaFieldNames,
    2087            0 :                             s_ipsc->cNumericFieldNames);
    2088              : 
    2089            0 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2090              : 
    2091            0 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    2092            0 :             ShowSevereDuplicateName(state, eoh);
    2093            0 :             ErrorsFound = true;
    2094            0 :             continue;
    2095              :         }
    2096              : 
    2097            0 :         auto *mat = new MaterialBlindEQL;
    2098            0 :         mat->group = Group::BlindEQL;
    2099            0 :         mat->Name = s_ipsc->cAlphaArgs(1);
    2100              : 
    2101            0 :         s_mat->materials.push_back(mat);
    2102            0 :         mat->Num = s_mat->materials.isize();
    2103            0 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    2104              : 
    2105            0 :         mat->Roughness = SurfaceRoughness::Rough;
    2106            0 :         mat->ROnly = true;
    2107              : 
    2108            0 :         mat->SlatOrientation =
    2109            0 :             static_cast<DataWindowEquivalentLayer::Orientation>(getEnumValue(DataWindowEquivalentLayer::orientationNamesUC, s_ipsc->cAlphaArgs(2)));
    2110              : 
    2111            0 :         mat->SlatWidth = s_ipsc->rNumericArgs(1);
    2112            0 :         mat->SlatSeparation = s_ipsc->rNumericArgs(2);
    2113            0 :         mat->SlatCrown = s_ipsc->rNumericArgs(3);
    2114            0 :         mat->SlatAngle = s_ipsc->rNumericArgs(4);
    2115              : 
    2116            0 :         mat->TAR.Sol.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(5);
    2117            0 :         mat->TAR.Sol.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(6);
    2118            0 :         mat->TAR.Sol.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(7);
    2119            0 :         mat->TAR.Sol.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(8);
    2120              : 
    2121            0 :         if (!s_ipsc->lNumericFieldBlanks(9) && !s_ipsc->lNumericFieldBlanks(10) && !s_ipsc->lNumericFieldBlanks(11) &&
    2122            0 :             !s_ipsc->lNumericFieldBlanks(12)) {
    2123            0 :             mat->TAR.Vis.Ft.Bm[0].DfTra = s_ipsc->rNumericArgs(9);
    2124            0 :             mat->TAR.Vis.Bk.Bm[0].DfTra = s_ipsc->rNumericArgs(10);
    2125            0 :             mat->TAR.Vis.Ft.Bm[0].DfRef = s_ipsc->rNumericArgs(11);
    2126            0 :             mat->TAR.Vis.Bk.Bm[0].DfRef = s_ipsc->rNumericArgs(12);
    2127              :         }
    2128            0 :         if (!s_ipsc->lNumericFieldBlanks(13) && !s_ipsc->lNumericFieldBlanks(14) && !s_ipsc->lNumericFieldBlanks(15)) {
    2129            0 :             mat->TAR.Sol.Ft.Df.Tra = s_ipsc->rNumericArgs(13);
    2130            0 :             mat->TAR.Sol.Ft.Df.Ref = s_ipsc->rNumericArgs(14);
    2131            0 :             mat->TAR.Sol.Bk.Df.Ref = s_ipsc->rNumericArgs(15);
    2132              :         }
    2133            0 :         if (!s_ipsc->lNumericFieldBlanks(16) && !s_ipsc->lNumericFieldBlanks(17) && !s_ipsc->lNumericFieldBlanks(18)) {
    2134            0 :             mat->TAR.Vis.Ft.Df.Tra = s_ipsc->rNumericArgs(13);
    2135            0 :             mat->TAR.Vis.Ft.Df.Ref = s_ipsc->rNumericArgs(14);
    2136            0 :             mat->TAR.Vis.Bk.Df.Ref = s_ipsc->rNumericArgs(15);
    2137              :         }
    2138            0 :         if (!s_ipsc->lNumericFieldBlanks(19)) {
    2139            0 :             mat->TAR.IR.Ft.Tra = mat->TAR.IR.Bk.Tra = s_ipsc->rNumericArgs(19);
    2140              :         }
    2141            0 :         if (!s_ipsc->lNumericFieldBlanks(20)) {
    2142            0 :             mat->TAR.IR.Ft.Emi = s_ipsc->rNumericArgs(20);
    2143              :         }
    2144            0 :         if (!s_ipsc->lNumericFieldBlanks(21)) {
    2145            0 :             mat->TAR.IR.Bk.Emi = s_ipsc->rNumericArgs(21);
    2146              :         }
    2147              :         // Assumes thermal emissivity is the same as thermal absorptance
    2148            0 :         mat->AbsorpThermalFront = mat->TAR.IR.Ft.Emi;
    2149            0 :         mat->AbsorpThermalBack = mat->TAR.IR.Bk.Emi;
    2150            0 :         mat->TransThermal = mat->TAR.IR.Ft.Tra;
    2151              : 
    2152              :         // By default all blinds have fixed slat angle,
    2153              :         //  they are used with window shading controls that adjust slat angles like
    2154              :         //  MaximizeSolar or BlockBeamSolar
    2155            0 :         mat->slatAngleType = SlatAngleType::FixedSlatAngle;
    2156            0 :         if (!s_ipsc->lAlphaFieldBlanks(3)) {
    2157            0 :             mat->slatAngleType = static_cast<SlatAngleType>(getEnumValue(slatAngleTypeNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(3))));
    2158              :         }
    2159            0 :         if (mat->SlatWidth < mat->SlatSeparation) {
    2160            0 :             ShowWarningError(state, format("{}=\"{}\", Slat Seperation/Width", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2161            0 :             ShowContinueError(state,
    2162            0 :                               format("{} [{:.2R}] is less than {} [{:.2R}].",
    2163            0 :                                      s_ipsc->cNumericFieldNames(1),
    2164            0 :                                      mat->SlatWidth,
    2165            0 :                                      s_ipsc->cNumericFieldNames(2),
    2166            0 :                                      mat->SlatSeparation));
    2167            0 :             ShowContinueError(state, "This will allow direct beam to be transmitted when Slat angle = 0.");
    2168              :         }
    2169            0 :         if (mat->SlatSeparation < 0.001) {
    2170            0 :             ShowWarningError(state, format("{}=\"{}\", Slat Seperation", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2171            0 :             ShowContinueError(state, format("{} [{:.2R}]. Slate spacing must be > 0.0", s_ipsc->cNumericFieldNames(2), mat->SlatSeparation));
    2172            0 :             ShowContinueError(state,
    2173              :                               "...Setting slate spacing to default value of 0.025 m and "
    2174              :                               "simulation continues.");
    2175            0 :             mat->SlatSeparation = 0.025;
    2176              :         }
    2177            0 :         if (mat->SlatWidth < 0.001 || mat->SlatWidth >= 2.0 * mat->SlatSeparation) {
    2178            0 :             ShowWarningError(state, format("{}=\"{}\", Slat Width", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2179            0 :             ShowContinueError(state,
    2180            0 :                               format("{} [{:.2R}]. Slat width range is 0 < Width <= 2*Spacing", s_ipsc->cNumericFieldNames(1), mat->SlatWidth));
    2181            0 :             ShowContinueError(state, "...Setting slate width equal to slate spacing and simulation continues.");
    2182            0 :             mat->SlatWidth = mat->SlatSeparation;
    2183              :         }
    2184            0 :         if (mat->SlatCrown < 0.0 || mat->SlatCrown >= 0.5 * mat->SlatWidth) {
    2185            0 :             ShowWarningError(state, format("{}=\"{}\", Slat Crown", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2186            0 :             ShowContinueError(state,
    2187            0 :                               format("{} [{:.2R}]. Slat crwon range is 0 <= crown < 0.5*Width", s_ipsc->cNumericFieldNames(3), mat->SlatCrown));
    2188            0 :             ShowContinueError(state, "...Setting slate crown to 0.0 and simulation continues.");
    2189            0 :             mat->SlatCrown = 0.0;
    2190              :         }
    2191            0 :         if (mat->SlatAngle < -90.0 || mat->SlatAngle > 90.0) {
    2192            0 :             ShowWarningError(state, format("{}=\"{}\", Slat Angle", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2193            0 :             ShowContinueError(state, format("{} [{:.2R}]. Slat angle range is -90.0 <= Angle < 90.0", s_ipsc->cNumericFieldNames(4), mat->SlatAngle));
    2194            0 :             ShowContinueError(state, "...Setting slate angle to 0.0 and simulation continues.");
    2195            0 :             mat->SlatAngle = 0.0;
    2196              :         }
    2197              : 
    2198            0 :         if ((s_ipsc->rNumericArgs(5) + s_ipsc->rNumericArgs(7) >= 1.0)) {
    2199            0 :             ErrorsFound = true;
    2200            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2201            0 :             ShowContinueError(state, format("{} + {} not < 1.0", s_ipsc->cNumericFieldNames(5), s_ipsc->cNumericFieldNames(7)));
    2202              :         }
    2203            0 :         if ((s_ipsc->rNumericArgs(6) + s_ipsc->rNumericArgs(8) >= 1.0)) {
    2204            0 :             ErrorsFound = true;
    2205            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2206            0 :             ShowContinueError(state, format("{} + {} not < 1.0", s_ipsc->cNumericFieldNames(6), s_ipsc->cNumericFieldNames(8)));
    2207              :         }
    2208            0 :         if ((s_ipsc->rNumericArgs(9) + s_ipsc->rNumericArgs(11) >= 1.0)) {
    2209            0 :             ErrorsFound = true;
    2210            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2211            0 :             ShowContinueError(state, format("{} + {} not < 1.0", s_ipsc->cNumericFieldNames(9), s_ipsc->cNumericFieldNames(11)));
    2212              :         }
    2213            0 :         if ((s_ipsc->rNumericArgs(10) + s_ipsc->rNumericArgs(12) >= 1.0)) {
    2214            0 :             ErrorsFound = true;
    2215            0 :             ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2216            0 :             ShowContinueError(state, format("{} + {} not < 1.0", s_ipsc->cNumericFieldNames(10), s_ipsc->cNumericFieldNames(12)));
    2217              :         }
    2218              : 
    2219              :     } // TotBlindsEQL loop
    2220              : 
    2221              :     // EcoRoof Materials
    2222              :     // PSU 2006
    2223          801 :     s_ipsc->cCurrentModuleObject = "Material:RoofVegetation";
    2224          801 :     s_mat->NumEcoRoofs = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2225          813 :     for (int Loop = 1; Loop <= s_mat->NumEcoRoofs; ++Loop) {
    2226              :         // Call Input Get Routine to retrieve material data from ecoroof
    2227              : 
    2228           24 :         s_ip->getObjectItem(state,
    2229           12 :                             s_ipsc->cCurrentModuleObject,
    2230              :                             Loop,
    2231           12 :                             s_ipsc->cAlphaArgs,
    2232              :                             NumAlphas,
    2233           12 :                             s_ipsc->rNumericArgs,
    2234              :                             NumNums,
    2235              :                             IOStat,
    2236           12 :                             s_ipsc->lNumericFieldBlanks,
    2237           12 :                             s_ipsc->lAlphaFieldBlanks,
    2238           12 :                             s_ipsc->cAlphaFieldNames,
    2239           12 :                             s_ipsc->cNumericFieldNames);
    2240              : 
    2241           12 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2242              : 
    2243           12 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    2244            0 :             ShowSevereDuplicateName(state, eoh);
    2245            0 :             ErrorsFound = true;
    2246            0 :             continue;
    2247              :         }
    2248              : 
    2249              :         // this part is similar to the regular material
    2250              :         // Load the material derived type from the input data.
    2251           12 :         auto *mat = new MaterialEcoRoof;
    2252           12 :         mat->group = Group::EcoRoof;
    2253           12 :         mat->Name = s_ipsc->cAlphaArgs(1);
    2254              : 
    2255           12 :         s_mat->materials.push_back(mat);
    2256           12 :         mat->Num = s_mat->materials.isize();
    2257           12 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    2258              : 
    2259           12 :         mat->HeightOfPlants = s_ipsc->rNumericArgs(1);
    2260           12 :         mat->LAI = s_ipsc->rNumericArgs(2);
    2261           12 :         mat->Lreflectivity = s_ipsc->rNumericArgs(3); // Albedo
    2262           12 :         mat->LEmissitivity = s_ipsc->rNumericArgs(4);
    2263           12 :         mat->RStomata = s_ipsc->rNumericArgs(5);
    2264              : 
    2265              :         // need to treat the A2 with is just the name of the soil(it is
    2266              :         // not important)
    2267           12 :         mat->Roughness = static_cast<SurfaceRoughness>(getEnumValue(surfaceRoughnessNamesUC, Util::makeUPPER(s_ipsc->cAlphaArgs(3))));
    2268              : 
    2269           12 :         if (s_ipsc->lAlphaFieldBlanks(4)) {
    2270            0 :             mat->calcMethod = EcoRoofCalcMethod::SchaapGenuchten;
    2271              :         } else {
    2272           12 :             mat->calcMethod = static_cast<EcoRoofCalcMethod>(getEnumValue(ecoRoofCalcMethodNamesUC, s_ipsc->cAlphaArgs(4)));
    2273              :         }
    2274              : 
    2275           12 :         mat->Thickness = s_ipsc->rNumericArgs(6);
    2276           12 :         mat->Conductivity = s_ipsc->rNumericArgs(7);
    2277           12 :         mat->Density = s_ipsc->rNumericArgs(8);
    2278           12 :         mat->SpecHeat = s_ipsc->rNumericArgs(9);
    2279           12 :         mat->AbsorpThermal = s_ipsc->rNumericArgs(10); // emissivity
    2280           12 :         mat->AbsorpSolar = s_ipsc->rNumericArgs(11);   // (1 - Albedo)
    2281           12 :         mat->AbsorpVisible = s_ipsc->rNumericArgs(12);
    2282           12 :         mat->Porosity = s_ipsc->rNumericArgs(13);
    2283           12 :         mat->MinMoisture = s_ipsc->rNumericArgs(14);
    2284           12 :         mat->InitMoisture = s_ipsc->rNumericArgs(15);
    2285              : 
    2286           12 :         if (mat->Conductivity > 0.0) {
    2287           12 :             mat->Resistance = mat->NominalR = mat->Thickness / mat->Conductivity;
    2288              :         } else {
    2289            0 :             ShowSevereError(state, format("{}=\"{}\" is not defined correctly.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2290            0 :             ShowContinueError(state, format("{} is <=0.", s_ipsc->cNumericFieldNames(7)));
    2291            0 :             ErrorsFound = true;
    2292              :         }
    2293              : 
    2294           12 :         if (mat->InitMoisture > mat->Porosity) {
    2295            0 :             ShowWarningError(state, format("{}=\"{}\", Illegal value combination.", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    2296            0 :             ShowContinueError(
    2297            0 :                 state, format("{} is greater than {}. It must be less or equal.", s_ipsc->cNumericFieldNames(15), s_ipsc->cNumericFieldNames(13)));
    2298            0 :             ShowContinueError(state, format("{} = {:.3T}.", s_ipsc->cNumericFieldNames(13), mat->Porosity));
    2299            0 :             ShowContinueError(state, format("{} = {:.3T}.", s_ipsc->cNumericFieldNames(15), mat->InitMoisture));
    2300            0 :             ShowContinueError(state,
    2301            0 :                               format("{} is reset to the maximum (saturation) value = {:.3T}.", s_ipsc->cNumericFieldNames(15), mat->Porosity));
    2302            0 :             ShowContinueError(state, "Simulation continues.");
    2303            0 :             mat->InitMoisture = mat->Porosity;
    2304              :         }
    2305              :     }
    2306              : 
    2307              :     // Thermochromic glazing group
    2308              :     // get the number of WindowMaterial:GlazingGroup:Thermochromic objects in the idf file
    2309          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:GlazingGroup:Thermochromic";
    2310          801 :     s_mat->NumTCGlazings = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2311              : 
    2312          802 :     for (int Loop = 1; Loop <= s_mat->NumTCGlazings; ++Loop) {
    2313              :         // Get each TCGlazings from the input processor
    2314            2 :         s_ip->getObjectItem(state,
    2315            1 :                             s_ipsc->cCurrentModuleObject,
    2316              :                             Loop,
    2317            1 :                             s_ipsc->cAlphaArgs,
    2318              :                             NumAlphas,
    2319            1 :                             s_ipsc->rNumericArgs,
    2320              :                             NumNums,
    2321              :                             IOStat,
    2322            1 :                             s_ipsc->lNumericFieldBlanks,
    2323            1 :                             s_ipsc->lAlphaFieldBlanks,
    2324            1 :                             s_ipsc->cAlphaFieldNames,
    2325            1 :                             s_ipsc->cNumericFieldNames);
    2326              : 
    2327            1 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2328            1 :         std::string nameUC = Util::makeUPPER(s_ipsc->cAlphaArgs(1));
    2329              : 
    2330            1 :         if (s_mat->materialMap.find(nameUC) != s_mat->materialMap.end()) {
    2331            0 :             ShowSevereDuplicateName(state, eoh);
    2332            0 :             ErrorsFound = true;
    2333            0 :             continue;
    2334              :         }
    2335              : 
    2336            1 :         auto *mat = new MaterialGlassTC;
    2337            1 :         mat->Name = s_ipsc->cAlphaArgs(1);
    2338            1 :         s_mat->materials.push_back(mat);
    2339            1 :         mat->Num = s_mat->materials.isize();
    2340            1 :         s_mat->materialMap.insert_or_assign(nameUC, mat->Num);
    2341              : 
    2342            1 :         if (NumNums + 1 != NumAlphas) {
    2343            0 :             ShowSevereCustom(
    2344            0 :                 state, eoh, format("Check number of {} compared to number of {}", s_ipsc->cAlphaFieldNames(2), s_ipsc->cNumericFieldNames(1)));
    2345            0 :             ErrorsFound = true;
    2346            0 :             continue;
    2347              :         }
    2348              : 
    2349              :         // Allocate arrays
    2350            1 :         mat->numMatRefs = NumNums;
    2351            1 :         mat->matRefs.allocate(mat->numMatRefs);
    2352              : 
    2353           20 :         for (int iMatRef = 1; iMatRef <= mat->numMatRefs; ++iMatRef) {
    2354           19 :             auto &matRef = mat->matRefs(iMatRef);
    2355           19 :             matRef.specTemp = s_ipsc->rNumericArgs(iMatRef);
    2356              :             // Find this glass definition
    2357           19 :             matRef.matNum = Material::GetMaterialNum(state, s_ipsc->cAlphaArgs(1 + iMatRef));
    2358           19 :             if (matRef.matNum == 0) {
    2359            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(1 + iMatRef), s_ipsc->cAlphaArgs(1 + iMatRef));
    2360            0 :                 ErrorsFound = true;
    2361            0 :                 continue;
    2362              :             }
    2363              : 
    2364              :             // TC glazing
    2365           19 :             auto *matGlass = s_mat->materials(matRef.matNum);
    2366              :             // test that named material is of the right type
    2367           19 :             if (matGlass->group != Group::Glass) {
    2368            0 :                 ShowSevereCustom(
    2369              :                     state,
    2370              :                     eoh,
    2371            0 :                     format("{} = {}, Material is not a window glazing ", s_ipsc->cAlphaFieldNames(1 + iMatRef), s_ipsc->cAlphaArgs(1 + iMatRef)));
    2372            0 :                 ErrorsFound = true;
    2373            0 :                 continue;
    2374              :             }
    2375              : 
    2376           19 :             dynamic_cast<MaterialGlass *>(matGlass)->TCParentMatNum = mat->Num;
    2377              :         }
    2378            1 :     }
    2379              : 
    2380          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:SimpleGlazingSystem";
    2381          801 :     s_mat->NumSimpleWindows = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2382          911 :     for (int Loop = 1; Loop <= s_mat->NumSimpleWindows; ++Loop) {
    2383              : 
    2384          220 :         s_ip->getObjectItem(state,
    2385          110 :                             s_ipsc->cCurrentModuleObject,
    2386              :                             Loop,
    2387          110 :                             s_ipsc->cAlphaArgs,
    2388              :                             NumAlphas,
    2389          110 :                             s_ipsc->rNumericArgs,
    2390              :                             NumNums,
    2391              :                             IOStat,
    2392          110 :                             s_ipsc->lNumericFieldBlanks,
    2393          110 :                             s_ipsc->lAlphaFieldBlanks,
    2394          110 :                             s_ipsc->cAlphaFieldNames,
    2395          110 :                             s_ipsc->cNumericFieldNames);
    2396              : 
    2397          110 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2398              : 
    2399          110 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    2400            0 :             ShowSevereDuplicateName(state, eoh);
    2401            0 :             ErrorsFound = true;
    2402            0 :             continue;
    2403              :         }
    2404              : 
    2405          110 :         auto *mat = new MaterialGlass;
    2406          110 :         mat->group = Group::GlassSimple;
    2407          110 :         mat->Name = s_ipsc->cAlphaArgs(1);
    2408              : 
    2409          110 :         s_mat->materials.push_back(mat);
    2410          110 :         mat->Num = s_mat->materials.isize();
    2411          110 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    2412              : 
    2413          110 :         mat->SimpleWindowUfactor = s_ipsc->rNumericArgs(1);
    2414          110 :         mat->SimpleWindowSHGC = s_ipsc->rNumericArgs(2);
    2415          110 :         if (!s_ipsc->lNumericFieldBlanks(3)) {
    2416           48 :             mat->SimpleWindowVisTran = s_ipsc->rNumericArgs(3);
    2417           48 :             mat->SimpleWindowVTinputByUser = true;
    2418              :         }
    2419              : 
    2420          110 :         mat->SetupSimpleWindowGlazingSystem(state);
    2421              :     }
    2422              : 
    2423              :     // Reading WindowMaterial:Gap, this will also read the
    2424              :     // WindowMaterial:DeflectionState and WindowMaterial:SupportPillar
    2425              :     // objects if necessary
    2426          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:Gap";
    2427          801 :     s_mat->NumW7Gaps = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2428              :     // ALLOCATE(DeflectionState(W7DeflectionStates))
    2429          815 :     for (int Loop = 1; Loop <= s_mat->NumW7Gaps; ++Loop) {
    2430           28 :         s_ip->getObjectItem(state,
    2431           14 :                             s_ipsc->cCurrentModuleObject,
    2432              :                             Loop,
    2433           14 :                             s_ipsc->cAlphaArgs,
    2434              :                             NumAlphas,
    2435           14 :                             s_ipsc->rNumericArgs,
    2436              :                             NumNums,
    2437              :                             IOStat,
    2438           14 :                             s_ipsc->lNumericFieldBlanks,
    2439           14 :                             s_ipsc->lAlphaFieldBlanks,
    2440           14 :                             s_ipsc->cAlphaFieldNames,
    2441           14 :                             s_ipsc->cNumericFieldNames);
    2442              : 
    2443           14 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2444              : 
    2445           14 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    2446            0 :             ShowSevereDuplicateName(state, eoh);
    2447            0 :             ErrorsFound = true;
    2448            0 :             continue;
    2449              :         }
    2450              : 
    2451           14 :         auto *mat = new Material::MaterialComplexWindowGap;
    2452           14 :         mat->Name = s_ipsc->cAlphaArgs(1);
    2453              : 
    2454           14 :         s_mat->materials.push_back(mat);
    2455           14 :         mat->Num = s_mat->materials.isize();
    2456           14 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    2457              : 
    2458           14 :         mat->group = Material::Group::ComplexWindowGap;
    2459           14 :         mat->Roughness = Material::SurfaceRoughness::Rough;
    2460           14 :         mat->ROnly = true;
    2461              : 
    2462           14 :         mat->Thickness = s_ipsc->rNumericArgs(1);
    2463           14 :         if (s_ipsc->rNumericArgs(1) <= 0.0) {
    2464            0 :             ErrorsFound = true;
    2465            0 :             ShowSevereCustom(state, eoh, format("{} must be > 0, entered {:.2R}", s_ipsc->cNumericFieldNames(1), s_ipsc->rNumericArgs(1)));
    2466              :         }
    2467              : 
    2468           14 :         mat->Pressure = s_ipsc->rNumericArgs(2);
    2469           14 :         if (s_ipsc->rNumericArgs(2) <= 0.0) {
    2470            0 :             ErrorsFound = true;
    2471            0 :             ShowSevereCustom(state, eoh, format("{} must be > 0, entered {:.2R}", s_ipsc->cNumericFieldNames(2), s_ipsc->rNumericArgs(2)));
    2472              :         }
    2473              : 
    2474           14 :         if (!s_ipsc->lAlphaFieldBlanks(2)) {
    2475           14 :             int matGasNum = GetMaterialNum(state, s_ipsc->cAlphaArgs(2));
    2476           14 :             if (matGasNum == 0) {
    2477            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2));
    2478            0 :                 ErrorsFound = true;
    2479            0 :                 continue;
    2480              :             }
    2481              : 
    2482              :             // Copy all relevant fields from referenced gas mixture
    2483           14 :             auto const *matGasMix = dynamic_cast<MaterialGasMix const *>(s_mat->materials(matGasNum));
    2484           14 :             mat->numGases = matGasMix->numGases;
    2485           14 :             mat->gasFracts = matGasMix->gasFracts;
    2486           14 :             mat->gases = matGasMix->gases;
    2487           14 :             mat->gapVentType = matGasMix->gapVentType;
    2488              :         }
    2489              : 
    2490              :         // Find referenced DeflectionState object and copy field from it
    2491           14 :         if (!s_ipsc->lAlphaFieldBlanks(3)) {
    2492            2 :             auto const itInstances = s_ip->epJSON.find("WindowGap:DeflectionState");
    2493            1 :             if (itInstances == s_ip->epJSON.end()) {
    2494            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3));
    2495            0 :                 ErrorsFound = true;
    2496            0 :                 continue;
    2497              :             }
    2498              : 
    2499            1 :             auto const &instances2 = itInstances.value();
    2500            1 :             auto itObj = instances2.begin();
    2501              :             // Can't use find here because epJSON keys are not upper-cased
    2502            1 :             for (; itObj != instances2.end(); ++itObj) {
    2503            1 :                 if (Util::makeUPPER(itObj.key()) == s_ipsc->cAlphaArgs(3)) {
    2504            1 :                     break;
    2505              :                 }
    2506              :             }
    2507              : 
    2508            1 :             if (itObj == instances2.end()) {
    2509            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3));
    2510            0 :                 ErrorsFound = true;
    2511            0 :                 continue;
    2512              :             }
    2513              : 
    2514            1 :             auto const &obj = itObj.value();
    2515            2 :             auto const &objSchemaProps = s_ip->getObjectSchemaProps(state, "WindowGap:DeflectionState");
    2516            2 :             mat->deflectedThickness = s_ip->getRealFieldValue(obj, objSchemaProps, "deflected_thickness");
    2517            1 :         }
    2518              : 
    2519              :         // Find referenced
    2520           14 :         if (!s_ipsc->lAlphaFieldBlanks(4)) {
    2521            2 :             auto const itInstances = s_ip->epJSON.find("WindowGap:SupportPillar");
    2522            1 :             if (itInstances == s_ip->epJSON.end()) {
    2523            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4));
    2524            0 :                 ErrorsFound = true;
    2525            0 :                 continue;
    2526              :             }
    2527              : 
    2528            1 :             auto const &instances3 = itInstances.value();
    2529              : 
    2530            1 :             auto itObj = instances3.begin();
    2531              :             // Can't use find here because epJSON keys are not upper-cased
    2532            1 :             for (; itObj != instances3.end(); ++itObj) {
    2533            1 :                 if (Util::makeUPPER(itObj.key()) == s_ipsc->cAlphaArgs(4)) {
    2534            1 :                     break;
    2535              :                 }
    2536              :             }
    2537              : 
    2538            1 :             if (itObj == instances3.end()) {
    2539            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4));
    2540            0 :                 ErrorsFound = true;
    2541            0 :                 continue;
    2542              :             }
    2543              : 
    2544            1 :             auto const &obj = itObj.value();
    2545            2 :             auto const &objSchemaProps = s_ip->getObjectSchemaProps(state, "WindowGap:SupportPillar");
    2546            2 :             mat->pillarSpacing = s_ip->getRealFieldValue(obj, objSchemaProps, "spacing");
    2547            2 :             mat->pillarRadius = s_ip->getRealFieldValue(obj, objSchemaProps, "radius");
    2548            1 :         }
    2549              :     }
    2550              : 
    2551              :     // Reading WindowMaterial:ComplexShade
    2552          801 :     s_ipsc->cCurrentModuleObject = "WindowMaterial:ComplexShade";
    2553          801 :     int TotComplexShades = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2554          810 :     for (int Loop = 1; Loop <= TotComplexShades; ++Loop) {
    2555           18 :         s_ip->getObjectItem(state,
    2556            9 :                             s_ipsc->cCurrentModuleObject,
    2557              :                             Loop,
    2558            9 :                             s_ipsc->cAlphaArgs,
    2559              :                             NumAlphas,
    2560            9 :                             s_ipsc->rNumericArgs,
    2561              :                             NumNums,
    2562              :                             IOStat,
    2563            9 :                             s_ipsc->lNumericFieldBlanks,
    2564            9 :                             s_ipsc->lAlphaFieldBlanks,
    2565            9 :                             s_ipsc->cAlphaFieldNames,
    2566            9 :                             s_ipsc->cNumericFieldNames);
    2567              : 
    2568            9 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2569              : 
    2570            9 :         if (s_mat->materialMap.find(s_ipsc->cAlphaArgs(1)) != s_mat->materialMap.end()) {
    2571            0 :             ShowSevereDuplicateName(state, eoh);
    2572            0 :             ErrorsFound = true;
    2573            0 :             continue;
    2574              :         }
    2575              : 
    2576            9 :         auto *mat = new Material::MaterialComplexShade;
    2577            9 :         mat->Name = s_ipsc->cAlphaArgs(1);
    2578              : 
    2579            9 :         s_mat->materials.push_back(mat);
    2580            9 :         mat->Num = s_mat->materials.isize();
    2581            9 :         s_mat->materialMap.insert_or_assign(mat->Name, mat->Num);
    2582              : 
    2583            9 :         mat->Roughness = Material::SurfaceRoughness::Rough;
    2584            9 :         mat->ROnly = true;
    2585              : 
    2586            9 :         mat->LayerType = static_cast<TARCOGParams::TARCOGLayerType>(getEnumValue(TARCOGParams::layerTypeNamesUC, s_ipsc->cAlphaArgs(2)));
    2587              : 
    2588            9 :         mat->Thickness = s_ipsc->rNumericArgs(1);
    2589            9 :         mat->Conductivity = s_ipsc->rNumericArgs(2);
    2590            9 :         mat->TransThermal = s_ipsc->rNumericArgs(3);
    2591            9 :         mat->FrontEmissivity = s_ipsc->rNumericArgs(4);
    2592            9 :         mat->BackEmissivity = s_ipsc->rNumericArgs(5);
    2593              : 
    2594              :         // Simon: in heat balance radiation exchange routines AbsorpThermal is used
    2595              :         // and program will crash if value is not assigned.  Not sure if this is correct
    2596              :         // or some additional calculation is necessary. Simon TODO
    2597            9 :         mat->AbsorpThermal = s_ipsc->rNumericArgs(5);
    2598            9 :         mat->AbsorpThermalFront = s_ipsc->rNumericArgs(4);
    2599            9 :         mat->AbsorpThermalBack = s_ipsc->rNumericArgs(5);
    2600              : 
    2601            9 :         mat->topOpeningMult = s_ipsc->rNumericArgs(6);
    2602            9 :         mat->bottomOpeningMult = s_ipsc->rNumericArgs(7);
    2603            9 :         mat->leftOpeningMult = s_ipsc->rNumericArgs(8);
    2604            9 :         mat->rightOpeningMult = s_ipsc->rNumericArgs(9);
    2605            9 :         mat->frontOpeningMult = s_ipsc->rNumericArgs(10);
    2606              : 
    2607            9 :         mat->SlatWidth = s_ipsc->rNumericArgs(11);
    2608            9 :         mat->SlatSpacing = s_ipsc->rNumericArgs(12);
    2609            9 :         mat->SlatThickness = s_ipsc->rNumericArgs(13);
    2610            9 :         mat->SlatAngle = s_ipsc->rNumericArgs(14);
    2611            9 :         mat->SlatConductivity = s_ipsc->rNumericArgs(15);
    2612            9 :         mat->SlatCurve = s_ipsc->rNumericArgs(16);
    2613              : 
    2614            9 :         if (s_ipsc->rNumericArgs(1) <= 0.0) {
    2615            0 :             ErrorsFound = true;
    2616            0 :             ShowSevereCustom(state, eoh, format("{} must be > 0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(1), s_ipsc->rNumericArgs(1)));
    2617              :         }
    2618              : 
    2619            9 :         if (s_ipsc->rNumericArgs(2) <= 0.0) {
    2620            0 :             ErrorsFound = true;
    2621            0 :             ShowSevereCustom(state, eoh, format("{} must be > 0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(2), s_ipsc->rNumericArgs(2)));
    2622              :         }
    2623              : 
    2624            9 :         if ((s_ipsc->rNumericArgs(3) < 0.0) || (s_ipsc->rNumericArgs(3) > 1.0)) {
    2625            0 :             ErrorsFound = true;
    2626            0 :             ShowSevereCustom(
    2627            0 :                 state, eoh, format("{} value must be >= 0 and <= 1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(3), s_ipsc->rNumericArgs(3)));
    2628              :         }
    2629              : 
    2630            9 :         if ((s_ipsc->rNumericArgs(4) <= 0.0) || (s_ipsc->rNumericArgs(4) > 1.0)) {
    2631            0 :             ErrorsFound = true;
    2632            0 :             ShowSevereCustom(
    2633            0 :                 state, eoh, format("{} value must be >= 0 and <= 1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(4), s_ipsc->rNumericArgs(4)));
    2634              :         }
    2635              : 
    2636            9 :         if ((s_ipsc->rNumericArgs(5) <= 0.0) || (s_ipsc->rNumericArgs(5) > 1.0)) {
    2637            0 :             ErrorsFound = true;
    2638            0 :             ShowSevereCustom(
    2639            0 :                 state, eoh, format("{} value must be >= 0 and <= 1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(5), s_ipsc->rNumericArgs(5)));
    2640              :         }
    2641              : 
    2642            9 :         if ((s_ipsc->rNumericArgs(6) < 0.0) || (s_ipsc->rNumericArgs(6) > 1.0)) {
    2643            0 :             ErrorsFound = true;
    2644            0 :             ShowSevereCustom(
    2645            0 :                 state, eoh, format("{} must be >= 0 or <= 1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(6), s_ipsc->rNumericArgs(6)));
    2646              :         }
    2647              : 
    2648            9 :         if ((s_ipsc->rNumericArgs(7) < 0.0) || (s_ipsc->rNumericArgs(7) > 1.0)) {
    2649            0 :             ErrorsFound = true;
    2650            0 :             ShowSevereCustom(state, eoh, format("{} must be >=0 or <=1, entered {:.2R}", s_ipsc->cNumericFieldNames(7), s_ipsc->rNumericArgs(7)));
    2651              :         }
    2652              : 
    2653            9 :         if ((s_ipsc->rNumericArgs(8) < 0.0) || (s_ipsc->rNumericArgs(8) > 1.0)) {
    2654            0 :             ErrorsFound = true;
    2655            0 :             ShowSevereCustom(
    2656            0 :                 state, eoh, format("{} must be >=0 or <=1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(8), s_ipsc->rNumericArgs(8)));
    2657              :         }
    2658              : 
    2659            9 :         if ((s_ipsc->rNumericArgs(9) < 0.0) || (s_ipsc->rNumericArgs(9) > 1.0)) {
    2660            0 :             ErrorsFound = true;
    2661            0 :             ShowSevereCustom(
    2662            0 :                 state, eoh, format("{} must be >=0 or <=1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(9), s_ipsc->rNumericArgs(9)));
    2663              :         }
    2664              : 
    2665            9 :         if ((s_ipsc->rNumericArgs(10) < 0.0) || (s_ipsc->rNumericArgs(10) > 1.0)) {
    2666            0 :             ErrorsFound = true;
    2667            0 :             ShowSevereCustom(
    2668            0 :                 state, eoh, format("{} must be >=0 or <=1, entered value = {:.2R}", s_ipsc->cNumericFieldNames(10), s_ipsc->rNumericArgs(10)));
    2669              :         }
    2670              : 
    2671            9 :         if ((mat->LayerType == TARCOGParams::TARCOGLayerType::VENETBLIND_HORIZ) ||
    2672            7 :             (mat->LayerType == TARCOGParams::TARCOGLayerType::VENETBLIND_VERT)) {
    2673            3 :             if (s_ipsc->rNumericArgs(11) <= 0.0) {
    2674            0 :                 ErrorsFound = true;
    2675            0 :                 ShowSevereCustom(
    2676            0 :                     state, eoh, format("{} must be >0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(11), s_ipsc->rNumericArgs(11)));
    2677              :             }
    2678              : 
    2679            3 :             if (s_ipsc->rNumericArgs(12) <= 0.0) {
    2680            0 :                 ErrorsFound = true;
    2681            0 :                 ShowSevereCustom(
    2682            0 :                     state, eoh, format("{} must be >0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(12), s_ipsc->rNumericArgs(12)));
    2683              :             }
    2684              : 
    2685            3 :             if (s_ipsc->rNumericArgs(13) <= 0.0) {
    2686            0 :                 ErrorsFound = true;
    2687            0 :                 ShowSevereCustom(
    2688            0 :                     state, eoh, format("{} must be >0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(13), s_ipsc->rNumericArgs(13)));
    2689              :             }
    2690              : 
    2691            3 :             if ((s_ipsc->rNumericArgs(14) < -90.0) || (s_ipsc->rNumericArgs(14) > 90.0)) {
    2692            0 :                 ErrorsFound = true;
    2693            0 :                 ShowSevereCustom(
    2694              :                     state,
    2695              :                     eoh,
    2696            0 :                     format("{} must be >=-90 and <=90, entered value = {:.2R}", s_ipsc->cNumericFieldNames(14), s_ipsc->rNumericArgs(14)));
    2697              :             }
    2698              : 
    2699            3 :             if (s_ipsc->rNumericArgs(15) <= 0.0) {
    2700            0 :                 ErrorsFound = true;
    2701            0 :                 ShowSevereCustom(
    2702            0 :                     state, eoh, format("{} must be >0, entered value = {:.2R}", s_ipsc->cNumericFieldNames(15), s_ipsc->rNumericArgs(15)));
    2703              :             }
    2704              : 
    2705            6 :             if ((s_ipsc->rNumericArgs(16) < 0.0) ||
    2706            3 :                 ((s_ipsc->rNumericArgs(16) > 0.0) && (s_ipsc->rNumericArgs(16) < (s_ipsc->rNumericArgs(11) / 2)))) {
    2707            0 :                 ErrorsFound = true;
    2708            0 :                 ShowSevereCustom(state,
    2709              :                                  eoh,
    2710            0 :                                  format("{} must be = 0 or greater than SlatWidth/2, entered value = {:.2R}",
    2711            0 :                                         s_ipsc->cNumericFieldNames(16),
    2712            0 :                                         s_ipsc->rNumericArgs(16)));
    2713              :             }
    2714              :         }
    2715              : 
    2716            9 :         if (ErrorsFound) {
    2717            0 :             ShowFatalError(state, "Error in complex fenestration material input.");
    2718              :         }
    2719              :     }
    2720              : 
    2721          801 :     bool DoReport = false;
    2722              : 
    2723         2403 :     ScanForReports(state, "Constructions", DoReport, "Materials");
    2724              : 
    2725          801 :     if (DoReport) {
    2726              : 
    2727           14 :         print(state.files.eio,
    2728              :               "! <Material Details>,Material Name,ThermalResistance {{m2-K/w}},Roughness,Thickness {{m}},Conductivity "
    2729              :               "{{w/m-K}},Density {{kg/m3}},Specific Heat "
    2730              :               "{{J/kg-K}},Absorptance:Thermal,Absorptance:Solar,Absorptance:Visible\n");
    2731              : 
    2732           14 :         print(state.files.eio, "! <Material:Air>,Material Name,ThermalResistance {{m2-K/w}}\n");
    2733              : 
    2734              :         // Formats
    2735           14 :         constexpr std::string_view Format_701(" Material Details,{},{:.4R},{},{:.4R},{:.3R},{:.3R},{:.3R},{:.4R},{:.4R},{:.4R}\n");
    2736           14 :         constexpr std::string_view Format_702(" Material:Air,{},{:.4R}\n");
    2737              : 
    2738          279 :         for (auto const *mat : s_mat->materials) {
    2739              : 
    2740          265 :             switch (mat->group) {
    2741           11 :             case Group::AirGap: {
    2742           11 :                 print(state.files.eio, Format_702, mat->Name, mat->Resistance);
    2743           11 :             } break;
    2744          254 :             default: {
    2745          254 :                 print(state.files.eio,
    2746              :                       Format_701,
    2747          254 :                       mat->Name,
    2748          254 :                       mat->Resistance,
    2749          254 :                       surfaceRoughnessNames[(int)mat->Roughness],
    2750          254 :                       mat->Thickness,
    2751          254 :                       mat->Conductivity,
    2752          254 :                       mat->Density,
    2753          254 :                       mat->SpecHeat,
    2754          254 :                       mat->AbsorpThermal,
    2755          254 :                       mat->AbsorpSolar,
    2756          254 :                       mat->AbsorpVisible);
    2757          254 :             } break;
    2758              :             }
    2759              :         }
    2760              :     }
    2761              : 
    2762              :     //  FORMATS.
    2763              : 
    2764          801 :     if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // setup surface property EMS actuators
    2765              : 
    2766         2284 :         for (auto *mat : s_mat->materials) {
    2767         2208 :             if (mat->group != Group::Regular) {
    2768          338 :                 continue;
    2769              :             }
    2770              : 
    2771         1870 :             SetupEMSActuator(state,
    2772              :                              "Material",
    2773              :                              mat->Name,
    2774              :                              "Surface Property Solar Absorptance",
    2775              :                              "[ ]",
    2776         1870 :                              mat->AbsorpSolarEMSOverrideOn,
    2777         1870 :                              mat->AbsorpSolarEMSOverride);
    2778         1870 :             SetupEMSActuator(state,
    2779              :                              "Material",
    2780              :                              mat->Name,
    2781              :                              "Surface Property Thermal Absorptance",
    2782              :                              "[ ]",
    2783         1870 :                              mat->AbsorpThermalEMSOverrideOn,
    2784         1870 :                              mat->AbsorpThermalEMSOverride);
    2785         1870 :             SetupEMSActuator(state,
    2786              :                              "Material",
    2787              :                              mat->Name,
    2788              :                              "Surface Property Visible Absorptance",
    2789              :                              "[ ]",
    2790         1870 :                              mat->AbsorpVisibleEMSOverrideOn,
    2791         1870 :                              mat->AbsorpVisibleEMSOverride);
    2792              :         }
    2793              :     }
    2794              : 
    2795          801 :     GetVariableAbsorptanceInput(state, ErrorsFound); // Read variable thermal and solar absorptance add-on data
    2796          801 : }
    2797              : 
    2798          801 : void GetVariableAbsorptanceInput(EnergyPlusData &state, bool &errorsFound)
    2799              : {
    2800          801 :     constexpr std::string_view routineName = "GetVariableAbsorptanceInput";
    2801              : 
    2802              :     int IOStat; // IO Status when calling get input subroutine
    2803              :     int numAlphas;
    2804              :     int numNumbers;
    2805              : 
    2806          801 :     auto &s_ip = state.dataInputProcessing->inputProcessor;
    2807          801 :     auto &s_ipsc = state.dataIPShortCut;
    2808          801 :     auto &s_mat = state.dataMaterial;
    2809              : 
    2810          801 :     s_ipsc->cCurrentModuleObject = "MaterialProperty:VariableAbsorptance";
    2811          801 :     int numVariAbs = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2812          801 :     s_mat->AnyVariableAbsorptance = (numVariAbs > 0);
    2813          802 :     for (int i = 1; i <= numVariAbs; ++i) {
    2814              :         // Call Input Get routine to retrieve material data
    2815            2 :         s_ip->getObjectItem(state,
    2816            1 :                             s_ipsc->cCurrentModuleObject,
    2817              :                             i,
    2818            1 :                             s_ipsc->cAlphaArgs,
    2819              :                             numAlphas,
    2820            1 :                             s_ipsc->rNumericArgs,
    2821              :                             numNumbers,
    2822              :                             IOStat,
    2823            1 :                             s_ipsc->lNumericFieldBlanks,
    2824            1 :                             s_ipsc->lAlphaFieldBlanks,
    2825            1 :                             s_ipsc->cAlphaFieldNames,
    2826            1 :                             s_ipsc->cNumericFieldNames);
    2827              : 
    2828            1 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2829              : 
    2830              :         // Load the material derived type from the input data.
    2831            1 :         int matNum = Material::GetMaterialNum(state, s_ipsc->cAlphaArgs(2));
    2832            1 :         if (matNum == 0) {
    2833            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2));
    2834            0 :             errorsFound = true;
    2835            0 :             return;
    2836              :         }
    2837              : 
    2838            1 :         auto *mat = s_mat->materials(matNum);
    2839              : 
    2840            1 :         if (mat->group != Group::Regular) {
    2841            0 :             ShowSevereError(
    2842              :                 state,
    2843            0 :                 format("{}: Reference Material is not appropriate type for Thermal/Solar Absorptance properties, material={}, must have regular "
    2844              :                        "properties (Thermal/Solar Absorptance)",
    2845            0 :                        s_ipsc->cCurrentModuleObject,
    2846            0 :                        mat->Name));
    2847            0 :             errorsFound = true;
    2848            0 :             continue;
    2849              :         }
    2850              : 
    2851            1 :         mat->absorpVarCtrlSignal = VariableAbsCtrlSignal::SurfaceTemperature; // default value
    2852            1 :         mat->absorpVarCtrlSignal = static_cast<VariableAbsCtrlSignal>(getEnumValue(variableAbsCtrlSignalNamesUC, s_ipsc->cAlphaArgs(3)));
    2853              : 
    2854            1 :         mat->absorpThermalVarCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(4));
    2855            1 :         mat->absorpThermalVarSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(5));
    2856            1 :         mat->absorpSolarVarCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(6));
    2857            1 :         mat->absorpSolarVarSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(7));
    2858            1 :         if (mat->absorpVarCtrlSignal == VariableAbsCtrlSignal::Scheduled) {
    2859            0 :             if ((mat->absorpThermalVarSched == nullptr) && (mat->absorpSolarVarSched == nullptr)) {
    2860            0 :                 ShowSevereError(
    2861              :                     state,
    2862            0 :                     format("{}: Control signal \"Scheduled\" is chosen but both thermal and solar absorptance schedules are undefined, for object {}",
    2863            0 :                            s_ipsc->cCurrentModuleObject,
    2864            0 :                            s_ipsc->cAlphaArgs(1)));
    2865            0 :                 errorsFound = true;
    2866            0 :                 return;
    2867              :             }
    2868            0 :             if ((mat->absorpThermalVarCurve != nullptr) || (mat->absorpSolarVarCurve != nullptr)) {
    2869            0 :                 ShowWarningError(state,
    2870            0 :                                  format("{}: Control signal \"Scheduled\" is chosen. Thermal or solar absorptance function name is going to be "
    2871              :                                         "ignored, for object {}",
    2872            0 :                                         s_ipsc->cCurrentModuleObject,
    2873            0 :                                         s_ipsc->cAlphaArgs(1)));
    2874            0 :                 errorsFound = true;
    2875            0 :                 return;
    2876              :             }
    2877              : 
    2878              :         } else { // controlled by performance table or curve
    2879            1 :             if ((mat->absorpThermalVarCurve == nullptr) && (mat->absorpSolarVarCurve == nullptr)) {
    2880            0 :                 ShowSevereError(state,
    2881            0 :                                 format("{}: Non-schedule control signal is chosen but both thermal and solar absorptance table or curve are "
    2882              :                                        "undefined, for object {}",
    2883            0 :                                        s_ipsc->cCurrentModuleObject,
    2884            0 :                                        s_ipsc->cAlphaArgs(1)));
    2885            0 :                 errorsFound = true;
    2886            0 :                 return;
    2887              :             }
    2888            1 :             if ((mat->absorpThermalVarSched != nullptr) || (mat->absorpSolarVarSched != nullptr)) {
    2889            0 :                 ShowWarningError(state,
    2890            0 :                                  format("{}: Non-schedule control signal is chosen. Thermal or solar absorptance schedule name is going to be "
    2891              :                                         "ignored, for object {}",
    2892            0 :                                         s_ipsc->cCurrentModuleObject,
    2893            0 :                                         s_ipsc->cAlphaArgs(1)));
    2894            0 :                 errorsFound = true;
    2895            0 :                 return;
    2896              :             }
    2897              :         }
    2898              :     }
    2899              : } // GetVariableAbsorptanceInput()
    2900              : 
    2901          801 : void GetWindowGlassSpectralData(EnergyPlusData &state, bool &ErrorsFound) // set to true if errors found in input
    2902              : {
    2903              : 
    2904              :     // SUBROUTINE INFORMATION:
    2905              :     //       AUTHOR         Fred Winkelmann
    2906              :     //       DATE WRITTEN   May 2000
    2907              : 
    2908              :     // PURPOSE OF THIS SUBROUTINE:
    2909              :     // Gets spectral data (transmittance, front reflectance, and back
    2910              :     // reflectance at normal incidence vs. wavelength) for glass
    2911              : 
    2912              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2913          801 :     constexpr std::string_view routineName = "GetWindowGlassSpectralData";
    2914              : 
    2915              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2916              :     int IOStat;    // IO Status when calling get input subroutine
    2917              :     int NumAlphas; // Number of spectral data alpha names being passed
    2918              :     int NumNums;   // Number of spectral data properties being passed
    2919              :     Real64 Lam;    // Wavelength (microns)
    2920              :     Real64 Tau;    // Transmittance, front reflectance, back reflectance
    2921              :     Real64 RhoF;
    2922              :     Real64 RhoB;
    2923              : 
    2924          801 :     auto &s_ip = state.dataInputProcessing->inputProcessor;
    2925          801 :     auto &s_ipsc = state.dataIPShortCut;
    2926          801 :     auto &s_mat = state.dataMaterial;
    2927              : 
    2928          801 :     constexpr int MaxSpectralDataElements = 800; // Maximum number in Spectral Data arrays.
    2929              : 
    2930          801 :     s_ipsc->cCurrentModuleObject = "MaterialProperty:GlazingSpectralData";
    2931          801 :     s_mat->NumSpectralData = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    2932              : 
    2933          801 :     if (s_mat->NumSpectralData == 0) {
    2934          778 :         return;
    2935              :     }
    2936              : 
    2937           23 :     s_mat->SpectralData.allocate(s_mat->NumSpectralData);
    2938              : 
    2939          106 :     for (int Loop = 1; Loop <= s_mat->NumSpectralData; ++Loop) {
    2940              : 
    2941              :         // Call Input Get routine to retrieve spectral data
    2942              :         // Name is followed by up to 450 sets of normal-incidence measured values of
    2943              :         // [wavelength (microns), transmittance, front reflectance, back reflectance] for
    2944              :         // wavelengths covering the short-wave solar spectrum (from about 0.25 to 2.5 microns)
    2945          166 :         s_ip->getObjectItem(state,
    2946           83 :                             s_ipsc->cCurrentModuleObject,
    2947              :                             Loop,
    2948           83 :                             s_ipsc->cAlphaArgs,
    2949              :                             NumAlphas,
    2950           83 :                             s_ipsc->rNumericArgs,
    2951              :                             NumNums,
    2952              :                             IOStat,
    2953           83 :                             s_ipsc->lNumericFieldBlanks,
    2954           83 :                             s_ipsc->lAlphaFieldBlanks,
    2955           83 :                             s_ipsc->cAlphaFieldNames,
    2956           83 :                             s_ipsc->cNumericFieldNames);
    2957              : 
    2958           83 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    2959              : 
    2960           83 :         auto &specData = s_mat->SpectralData(Loop);
    2961              :         // Load the spectral data derived type from the input data.
    2962           83 :         specData.Name = s_ipsc->cAlphaArgs(1);
    2963           83 :         int TotLam = NumNums / 4;
    2964           83 :         if (mod(NumNums, 4) != 0) {
    2965            0 :             ShowWarningCustom(
    2966              :                 state,
    2967              :                 eoh,
    2968            0 :                 format("{} of items in data set is not a multiple of 4 (Wavelength,Trans,ReflFront,ReflBack), remainder items set to 0.0", NumNums));
    2969            0 :             ErrorsFound = true;
    2970            0 :             continue;
    2971              :         }
    2972              : 
    2973           83 :         if (TotLam > MaxSpectralDataElements) {
    2974            0 :             ShowSevereCustom(state, eoh, format("More than {} entries in set ({})", MaxSpectralDataElements, NumNums));
    2975            0 :             ErrorsFound = true;
    2976            0 :             continue;
    2977              :         }
    2978              : 
    2979           83 :         specData.NumOfWavelengths = TotLam;
    2980           83 :         specData.WaveLength.allocate(TotLam); // Wavelength (microns)
    2981           83 :         specData.Trans.allocate(TotLam);      // Transmittance at normal incidence
    2982           83 :         specData.ReflFront.allocate(TotLam);  // Front reflectance at normal incidence
    2983           83 :         specData.ReflBack.allocate(TotLam);   // Back reflectance at normal incidence
    2984              : 
    2985        27764 :         for (int LamNum = 1; LamNum <= TotLam; ++LamNum) {
    2986        27681 :             specData.WaveLength(LamNum) = s_ipsc->rNumericArgs(4 * LamNum - 3);
    2987        27681 :             specData.Trans(LamNum) = s_ipsc->rNumericArgs(4 * LamNum - 2);
    2988              :             // Following is needed since angular calculation in subr TransAndReflAtPhi
    2989              :             // fails for Trans = 0.0
    2990        27681 :             if (specData.Trans(LamNum) < 0.001) {
    2991          825 :                 specData.Trans(LamNum) = 0.001;
    2992              :             }
    2993        27681 :             specData.ReflFront(LamNum) = s_ipsc->rNumericArgs(4 * LamNum - 1);
    2994        27681 :             specData.ReflBack(LamNum) = s_ipsc->rNumericArgs(4 * LamNum);
    2995              :         }
    2996              : 
    2997              :         // Check integrity of the spectral data
    2998        27764 :         for (int LamNum = 1; LamNum <= TotLam; ++LamNum) {
    2999        27681 :             Lam = specData.WaveLength(LamNum);
    3000        27681 :             Tau = specData.Trans(LamNum);
    3001        27681 :             RhoF = specData.ReflFront(LamNum);
    3002        27681 :             RhoB = specData.ReflBack(LamNum);
    3003        27681 :             if (LamNum < TotLam && specData.WaveLength(LamNum + 1) <= Lam) {
    3004            0 :                 ErrorsFound = true;
    3005            0 :                 ShowSevereError(state, format("{}{}=\"{}\" invalid set.", routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    3006            0 :                 ShowContinueError(state,
    3007            0 :                                   format("... Wavelengths not in increasing order. at wavelength#={}, value=[{:.4T}], next is [{:.4T}].",
    3008              :                                          LamNum,
    3009              :                                          Lam,
    3010              :                                          specData.WaveLength(LamNum + 1)));
    3011              :             }
    3012              : 
    3013        27681 :             if (Lam < 0.1 || Lam > 4.0) {
    3014            0 :                 ErrorsFound = true;
    3015            0 :                 ShowSevereError(state, format("{}{}=\"{}\" invalid value.", routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    3016            0 :                 ShowContinueError(state,
    3017            0 :                                   format("... A wavelength is not in the range 0.1 to 4.0 microns; at wavelength#={}, value=[{:.4T}].", LamNum, Lam));
    3018              :             }
    3019              : 
    3020              :             // TH 2/15/2011. CR 8343
    3021              :             // IGDB (International Glazing Database) does not meet the above strict restrictions.
    3022              :             //  Relax rules to allow directly use of spectral data from IGDB
    3023        27681 :             if (Tau > 1.01) {
    3024            0 :                 ErrorsFound = true;
    3025            0 :                 ShowSevereError(state, format("{}: {}=\"{}\" invalid value.", routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    3026            0 :                 ShowContinueError(state, format("... A transmittance is > 1.0; at wavelength#={}, value=[{:.4T}].", LamNum, Tau));
    3027              :             }
    3028              : 
    3029        27681 :             if (RhoF < 0.0 || RhoF > 1.02 || RhoB < 0.0 || RhoB > 1.02) {
    3030            0 :                 ErrorsFound = true;
    3031            0 :                 ShowSevereError(state, format("{}: {}=\"{}\" invalid value.", routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    3032            0 :                 ShowContinueError(state, format("... A reflectance is < 0.0 or > 1.0; at wavelength#={}, RhoF value=[{:.4T}].", LamNum, RhoF));
    3033            0 :                 ShowContinueError(state, format("... A reflectance is < 0.0 or > 1.0; at wavelength#={}, RhoB value=[{:.4T}].", LamNum, RhoB));
    3034              :             }
    3035              : 
    3036        27681 :             if ((Tau + RhoF) > 1.03 || (Tau + RhoB) > 1.03) {
    3037            0 :                 ErrorsFound = true;
    3038            0 :                 ShowSevereError(state, format("{}: {}=\"{}\" invalid value.", routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    3039            0 :                 ShowContinueError(state,
    3040            0 :                                   format("... Transmittance + reflectance) > 1.0 for an entry; at wavelength#={}",
    3041            0 :                                          format("{}, value(Tau+RhoF)=[{:.4T}], value(Tau+RhoB)=[{:.4T}].", LamNum, (Tau + RhoF), (Tau + RhoB))));
    3042              :             }
    3043              :         }
    3044              :     }
    3045              : } // GetWindowGlassSpectralData()
    3046              : 
    3047          110 : void MaterialGlass::SetupSimpleWindowGlazingSystem(EnergyPlusData &state)
    3048              : {
    3049              : 
    3050              :     // SUBROUTINE INFORMATION:
    3051              :     //       AUTHOR         B. Griffith
    3052              :     //       DATE WRITTEN   January 2009
    3053              : 
    3054              :     // PURPOSE OF THIS SUBROUTINE:
    3055              :     // Convert simple window performance indices into all the properties needed to
    3056              :     // describe a single, equivalent glass layer
    3057              : 
    3058              :     // METHODOLOGY EMPLOYED:
    3059              :     // The simple window indices are converted to a single materal layer using a "block model"
    3060              : 
    3061              :     // REFERENCES:
    3062              :     // draft paper by Arasteh, Kohler, and Griffith
    3063              : 
    3064              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3065          110 :     Real64 Riw(0.0);            // thermal resistance of interior film coefficient under winter conditions (m2-K/W)
    3066          110 :     Real64 Row(0.0);            // theraml resistance of exterior film coefficient under winter conditions (m2-K/W)
    3067          110 :     Real64 Rlw(0.0);            // thermal resistance of block model layer (m2-K/W)
    3068          110 :     Real64 Ris(0.0);            // thermal resistance of interior film coefficient under summer conditions (m2-K/W)
    3069          110 :     Real64 Ros(0.0);            // theraml resistance of exterior film coefficient under summer conditions (m2-K/W)
    3070          110 :     Real64 InflowFraction(0.0); // inward flowing fraction for SHGC, intermediate value non dimensional
    3071          110 :     Real64 SolarAbsorb(0.0);    // solar aborptance
    3072          110 :     bool ErrorsFound(false);
    3073          110 :     Real64 TsolLowSide(0.0);      // intermediate solar transmission for interpolating
    3074          110 :     Real64 TsolHiSide(0.0);       // intermediate solar transmission for interpolating
    3075          110 :     Real64 DeltaSHGCandTsol(0.0); // intermediate difference
    3076          110 :     Real64 RLowSide(0.0);
    3077          110 :     Real64 RHiSide(0.0);
    3078              : 
    3079              :     // first fill out defaults
    3080          110 :     this->GlassSpectralDataPtr = 0;
    3081          110 :     this->SolarDiffusing = false;
    3082          110 :     this->Roughness = Material::SurfaceRoughness::VerySmooth;
    3083          110 :     this->TransThermal = 0.0;
    3084          110 :     this->AbsorpThermalBack = 0.84;
    3085          110 :     this->AbsorpThermalFront = 0.84;
    3086          110 :     this->AbsorpThermal = this->AbsorpThermalBack;
    3087              : 
    3088              :     // step 1. Determine U-factor without film coefficients
    3089              :     // Simple window model has its own correlation for film coefficients (m2-K/W) under Winter conditions as function of U-factor
    3090          110 :     if (this->SimpleWindowUfactor < 5.85) {
    3091          109 :         Riw = 1.0 / (0.359073 * std::log(this->SimpleWindowUfactor) + 6.949915);
    3092              :     } else {
    3093            1 :         Riw = 1.0 / (1.788041 * this->SimpleWindowUfactor - 2.886625);
    3094              :     }
    3095          110 :     Row = 1.0 / (0.025342 * this->SimpleWindowUfactor + 29.163853);
    3096              : 
    3097              :     // determine 1/U without film coefficients
    3098          110 :     Rlw = (1.0 / this->SimpleWindowUfactor) - Riw - Row;
    3099          110 :     if (Rlw <= 0.0) { // U factor of film coefficients is better than user input.
    3100            0 :         Rlw = max(Rlw, 0.001);
    3101            0 :         ShowWarningError(state,
    3102            0 :                          format("WindowMaterial:SimpleGlazingSystem: {} has U-factor higher than that provided by surface film resistances, "
    3103              :                                 "Check value of U-factor",
    3104            0 :                                 this->Name));
    3105              :     }
    3106              : 
    3107              :     // Step 2. determine layer thickness.
    3108              : 
    3109          110 :     if ((1.0 / Rlw) > 7.0) {
    3110           65 :         this->Thickness = 0.002;
    3111              :     } else {
    3112           45 :         this->Thickness = 0.05914 - (0.00714 / Rlw);
    3113              :     }
    3114              : 
    3115              :     // Step 3. determine effective conductivity
    3116              : 
    3117          110 :     this->Conductivity = this->Thickness / Rlw;
    3118          110 :     if (this->Conductivity > 0.0) {
    3119          110 :         this->NominalR = this->Resistance = Rlw;
    3120              :     } else {
    3121            0 :         ErrorsFound = true;
    3122            0 :         ShowSevereError(state,
    3123            0 :                         format("WindowMaterial:SimpleGlazingSystem: {} has Conductivity <= 0.0, must be >0.0, Check value of U-factor", this->Name));
    3124              :     }
    3125              : 
    3126              :     // step 4. determine solar transmission (revised to 10-1-2009 version from LBNL.)
    3127              : 
    3128          110 :     if (this->SimpleWindowUfactor > 4.5) {
    3129              : 
    3130            2 :         if (this->SimpleWindowSHGC < 0.7206) {
    3131              : 
    3132            1 :             this->Trans = 0.939998 * pow_2(this->SimpleWindowSHGC) + 0.20332 * this->SimpleWindowSHGC;
    3133              :         } else { // >= 0.7206
    3134            1 :             this->Trans = 1.30415 * this->SimpleWindowSHGC - 0.30515;
    3135              :         }
    3136              : 
    3137          108 :     } else if (this->SimpleWindowUfactor < 3.4) {
    3138              : 
    3139          106 :         if (this->SimpleWindowSHGC <= 0.15) {
    3140            0 :             this->Trans = 0.41040 * this->SimpleWindowSHGC;
    3141              :         } else { // > 0.15
    3142          106 :             this->Trans = 0.085775 * pow_2(this->SimpleWindowSHGC) + 0.963954 * this->SimpleWindowSHGC - 0.084958;
    3143              :         }
    3144              :     } else { // interpolate. 3.4 <= Ufactor <= 4.5
    3145              : 
    3146            2 :         if (this->SimpleWindowSHGC < 0.7206) {
    3147            2 :             TsolHiSide = 0.939998 * pow_2(this->SimpleWindowSHGC) + 0.20332 * this->SimpleWindowSHGC;
    3148              :         } else { // >= 0.7206
    3149            0 :             TsolHiSide = 1.30415 * this->SimpleWindowSHGC - 0.30515;
    3150              :         }
    3151              : 
    3152            2 :         if (this->SimpleWindowSHGC <= 0.15) {
    3153            0 :             TsolLowSide = 0.41040 * this->SimpleWindowSHGC;
    3154              :         } else { // > 0.15
    3155            2 :             TsolLowSide = 0.085775 * pow_2(this->SimpleWindowSHGC) + 0.963954 * this->SimpleWindowSHGC - 0.084958;
    3156              :         }
    3157              : 
    3158            2 :         this->Trans = ((this->SimpleWindowUfactor - 3.4) / (4.5 - 3.4)) * (TsolHiSide - TsolLowSide) + TsolLowSide;
    3159              :     }
    3160          110 :     if (this->Trans < 0.0) {
    3161            0 :         this->Trans = 0.0;
    3162              :     }
    3163              : 
    3164              :     // step 5.  determine solar reflectances
    3165              : 
    3166          110 :     DeltaSHGCandTsol = this->SimpleWindowSHGC - this->Trans;
    3167              : 
    3168          110 :     if (this->SimpleWindowUfactor > 4.5) {
    3169              : 
    3170            2 :         Ris = 1.0 / (29.436546 * pow_3(DeltaSHGCandTsol) - 21.943415 * pow_2(DeltaSHGCandTsol) + 9.945872 * DeltaSHGCandTsol + 7.426151);
    3171            2 :         Ros = 1.0 / (2.225824 * DeltaSHGCandTsol + 20.577080);
    3172          108 :     } else if (this->SimpleWindowUfactor < 3.4) {
    3173              : 
    3174          106 :         Ris = 1.0 / (199.8208128 * pow_3(DeltaSHGCandTsol) - 90.639733 * pow_2(DeltaSHGCandTsol) + 19.737055 * DeltaSHGCandTsol + 6.766575);
    3175          106 :         Ros = 1.0 / (5.763355 * DeltaSHGCandTsol + 20.541528);
    3176              :     } else { // interpolate. 3.4 <= Ufactor <= 4.5
    3177              :         // inside first
    3178            2 :         RLowSide = 1.0 / (199.8208128 * pow_3(DeltaSHGCandTsol) - 90.639733 * pow_2(DeltaSHGCandTsol) + 19.737055 * DeltaSHGCandTsol + 6.766575);
    3179            2 :         RHiSide = 1.0 / (29.436546 * pow_3(DeltaSHGCandTsol) - 21.943415 * pow_2(DeltaSHGCandTsol) + 9.945872 * DeltaSHGCandTsol + 7.426151);
    3180            2 :         Ris = ((this->SimpleWindowUfactor - 3.4) / (4.5 - 3.4)) * (RLowSide - RHiSide) + RLowSide;
    3181              :         // then outside
    3182            2 :         RLowSide = 1.0 / (5.763355 * DeltaSHGCandTsol + 20.541528);
    3183            2 :         RHiSide = 1.0 / (2.225824 * DeltaSHGCandTsol + 20.577080);
    3184            2 :         Ros = ((this->SimpleWindowUfactor - 3.4) / (4.5 - 3.4)) * (RLowSide - RHiSide) + RLowSide;
    3185              :     }
    3186              : 
    3187          110 :     InflowFraction = (Ros + 0.5 * Rlw) / (Ros + Rlw + Ris);
    3188              : 
    3189          110 :     SolarAbsorb = (this->SimpleWindowSHGC - this->Trans) / InflowFraction;
    3190          110 :     this->ReflectSolBeamBack = 1.0 - this->Trans - SolarAbsorb;
    3191          110 :     this->ReflectSolBeamFront = this->ReflectSolBeamBack;
    3192              : 
    3193              :     // step 6. determine visible properties.
    3194          110 :     if (this->SimpleWindowVTinputByUser) {
    3195           48 :         this->TransVis = this->SimpleWindowVisTran;
    3196           48 :         this->ReflectVisBeamBack = -0.7409 * pow_3(this->TransVis) + 1.6531 * pow_2(this->TransVis) - 1.2299 * this->TransVis + 0.4545;
    3197           48 :         if (this->TransVis + this->ReflectVisBeamBack >= 1.0) {
    3198            5 :             this->ReflectVisBeamBack = 0.999 - this->TransVis;
    3199              :         }
    3200              : 
    3201           48 :         this->ReflectVisBeamFront = -0.0622 * pow_3(this->TransVis) + 0.4277 * pow_2(this->TransVis) - 0.4169 * this->TransVis + 0.2399;
    3202           48 :         if (this->TransVis + this->ReflectVisBeamFront >= 1.0) {
    3203            5 :             this->ReflectVisBeamFront = 0.999 - this->TransVis;
    3204              :         }
    3205              :     } else {
    3206           62 :         this->TransVis = this->Trans;
    3207           62 :         this->ReflectVisBeamBack = this->ReflectSolBeamBack;
    3208           62 :         this->ReflectVisBeamFront = this->ReflectSolBeamFront;
    3209              :     }
    3210              : 
    3211              :     // step 7. The dependence on incident angle is in subroutine TransAndReflAtPhi
    3212              : 
    3213              :     // step 8.  Hemispherical terms are averaged using standard method
    3214              : 
    3215          110 :     if (ErrorsFound) {
    3216            0 :         ShowFatalError(state, "Program halted because of input problem(s) in WindowMaterial:SimpleGlazingSystem");
    3217              :     }
    3218          110 : } // MaterialGlass::SetupSimpleWindowGlazingSystem()
    3219              : 
    3220         3386 : void CalcScreenTransmittance([[maybe_unused]] EnergyPlusData &state,
    3221              :                              MaterialScreen const *screen,
    3222              :                              Real64 phi,   // Sun altitude relative to surface outward normal (radians, 0 to Pi)
    3223              :                              Real64 theta, // Optional sun azimuth relative to surface outward normal (radians, 0 to Pi)
    3224              :                              ScreenBmTransAbsRef &tar)
    3225              : {
    3226              : 
    3227              :     // FUNCTION INFORMATION:
    3228              :     //       AUTHOR         Richard Raustad
    3229              :     //       DATE WRITTEN   May 2006
    3230              :     //       MODIFIED       na
    3231              :     //       RE-ENGINEERED  na
    3232              : 
    3233              :     // PURPOSE OF THIS FUNCTION:
    3234              :     //  Calculate transmittance of window screen given azimuth and altitude angle
    3235              :     //  of sun and surface orientation.
    3236              : 
    3237              :     // METHODOLOGY EMPLOYED:
    3238              :     //  Window screen solar beam transmittance varies as the sun moves across the sky
    3239              :     //  due to the geometry of the screen material and the angle of incidence
    3240              :     //  of the solar beam. Azimuth and altitude angle are calculated with respect
    3241              :     //  to the surface outward normal. Solar beam reflectance and absorptance are also
    3242              :     //  accounted for.
    3243              : 
    3244         3386 :     Real64 constexpr Small(1.E-9); // Small Number used to approximate zero
    3245              : 
    3246              :     Real64 Tdirect;       // Beam solar transmitted through screen (dependent on sun angle)
    3247              :     Real64 Tscattered;    // Beam solar reflected through screen (dependent on sun angle)
    3248              :     Real64 TscatteredVis; // Visible beam solar reflected through screen (dependent on sun angle)
    3249              : 
    3250         3386 :     assert(phi >= 0.0 && phi <= Constant::Pi);
    3251         3386 :     assert(theta >= 0.0 && theta <= Constant::Pi);
    3252              : 
    3253         3386 :     Real64 sinPhi = std::sin(phi);
    3254         3386 :     Real64 cosPhi = std::cos(phi);
    3255         3386 :     Real64 tanPhi = sinPhi / cosPhi;
    3256         3386 :     Real64 cosTheta = std::cos(theta);
    3257              : 
    3258         3386 :     bool sunInFront = (phi < Constant::PiOvr2) && (theta < Constant::PiOvr2); // Sun is in front of screen
    3259              : 
    3260              :     // ratio of screen material diameter to screen material spacing
    3261         3386 :     Real64 Gamma = screen->diameterToSpacingRatio;
    3262              : 
    3263              :     // ************************************************************************************************
    3264              :     // * calculate transmittance of totally absorbing screen material (beam passing through open area)*
    3265              :     // ************************************************************************************************
    3266              : 
    3267              :     // Now we need to normalize phi and theta to the 0 to Pi/2 range using reflection.
    3268         3386 :     if (phi > Constant::PiOvr2) {
    3269         1332 :         phi = Constant::Pi - phi;
    3270              :     }
    3271         3386 :     if (theta > Constant::PiOvr2) {
    3272         1332 :         theta = Constant::Pi - theta;
    3273              :     }
    3274              : 
    3275              :     // calculate compliment of relative solar azimuth
    3276         3386 :     Real64 Beta = Constant::PiOvr2 - theta;
    3277              : 
    3278              :     // Catch all divide by zero instances
    3279              :     Real64 TransYDir;
    3280              :     Real64 TransXDir;
    3281         3386 :     if (Beta > Small && std::abs(phi - Constant::PiOvr2) > Small) {
    3282         3240 :         Real64 AlphaDblPrime = std::atan(tanPhi / cosTheta);
    3283         3240 :         TransYDir = 1.0 - Gamma * (std::cos(AlphaDblPrime) + std::sin(AlphaDblPrime) * tanPhi * std::sqrt(1.0 + pow_2(1.0 / std::tan(Beta))));
    3284         3240 :         TransYDir = max(0.0, TransYDir);
    3285              :     } else {
    3286          146 :         TransYDir = 0.0;
    3287              :     }
    3288              : 
    3289         3386 :     Real64 COSMu = std::sqrt(pow_2(cosPhi) * pow_2(cosTheta) + pow_2(sinPhi));
    3290         3386 :     if (COSMu <= Small) {
    3291            4 :         TransXDir = 1.0 - Gamma;
    3292              :     } else {
    3293         3382 :         Real64 Epsilon = std::acos(cosPhi * cosTheta / COSMu);
    3294         3382 :         Real64 Eta = Constant::PiOvr2 - Epsilon;
    3295         3382 :         if (std::cos(Epsilon) != 0.0 && Eta != 0.0) {
    3296         3282 :             Real64 MuPrime = std::atan(std::tan(std::acos(COSMu)) / std::cos(Epsilon));
    3297         3282 :             TransXDir =
    3298         3282 :                 1.0 - Gamma * (std::cos(MuPrime) + std::sin(MuPrime) * std::tan(std::acos(COSMu)) * std::sqrt(1.0 + pow_2(1.0 / std::tan(Eta))));
    3299         3282 :             TransXDir = max(0.0, TransXDir);
    3300         3282 :         } else {
    3301          100 :             TransXDir = 0.0;
    3302              :         }
    3303              :     }
    3304         3386 :     Tdirect = max(0.0, TransXDir * TransYDir);
    3305              : 
    3306              :     // *******************************************************************************
    3307              :     // * calculate transmittance of scattered beam due to reflecting screen material *
    3308              :     // *******************************************************************************
    3309              : 
    3310         3386 :     Real64 ReflCyl = screen->CylinderRef;
    3311         3386 :     Real64 ReflCylVis = screen->CylinderRefVis;
    3312              : 
    3313         3386 :     if ((Constant::PiOvr2 - theta) < Small || (Constant::PiOvr2 - phi) < Small) {
    3314          146 :         Tscattered = 0.0;
    3315          146 :         TscatteredVis = 0.0;
    3316              :     } else {
    3317              :         //   DeltaMax and Delta are in degrees
    3318         3240 :         Real64 DeltaMax = 89.7 - (10.0 * Gamma / 0.16);
    3319         3240 :         Real64 Delta = std::sqrt(pow_2(theta / Constant::DegToRad) + pow_2(phi / Constant::DegToRad));
    3320              : 
    3321              :         //   Use empirical model to determine maximum (peak) scattering
    3322         3240 :         Real64 Tscattermax = 0.0229 * Gamma + 0.2971 * ReflCyl - 0.03624 * pow_2(Gamma) + 0.04763 * pow_2(ReflCyl) - 0.44416 * Gamma * ReflCyl;
    3323              :         Real64 TscattermaxVis =
    3324         3240 :             0.0229 * Gamma + 0.2971 * ReflCylVis - 0.03624 * pow_2(Gamma) + 0.04763 * pow_2(ReflCylVis) - 0.44416 * Gamma * ReflCylVis;
    3325              : 
    3326              :         //   Vary slope of interior and exterior surface of scattering model
    3327         3240 :         Real64 ExponentInterior = -pow_2(Delta - DeltaMax) / 600.0;
    3328         3240 :         Real64 ExponentExterior = -std::pow(std::abs(Delta - DeltaMax), 2.5) / 600.0;
    3329              : 
    3330              :         //   Determine ratio of scattering at 0,0 incident angle to maximum (peak) scattering
    3331         3240 :         Real64 PeakToPlateauRatio = 1.0 / (0.2 * (1 - Gamma) * ReflCyl);
    3332         3240 :         Real64 PeakToPlateauRatioVis = 1.0 / (0.2 * (1 - Gamma) * ReflCylVis);
    3333              : 
    3334              :         //     Apply offset for plateau and use exterior exponential function to simulate actual scattering as a function of solar angles
    3335         3240 :         if (Delta > DeltaMax) {
    3336          968 :             Tscattered = 0.2 * (1.0 - Gamma) * ReflCyl * Tscattermax * (1.0 + (PeakToPlateauRatio - 1.0) * std::exp(ExponentExterior));
    3337          968 :             TscatteredVis = 0.2 * (1.0 - Gamma) * ReflCylVis * TscattermaxVis * (1.0 + (PeakToPlateauRatioVis - 1.0) * std::exp(ExponentExterior));
    3338              :             //     Trim off offset if solar angle (delta) is greater than maximum (peak) scattering angle
    3339          968 :             Tscattered -= (0.2 * (1.0 - Gamma) * ReflCyl * Tscattermax) * max(0.0, (Delta - DeltaMax) / (90.0 - DeltaMax));
    3340          968 :             TscatteredVis -= (0.2 * (1.0 - Gamma) * ReflCylVis * TscattermaxVis) * max(0.0, (Delta - DeltaMax) / (90.0 - DeltaMax));
    3341              :         } else {
    3342         2272 :             Tscattered = 0.2 * (1.0 - Gamma) * ReflCyl * Tscattermax * (1.0 + (PeakToPlateauRatio - 1.0) * std::exp(ExponentInterior));
    3343         2272 :             TscatteredVis = 0.2 * (1.0 - Gamma) * ReflCylVis * TscattermaxVis * (1.0 + (PeakToPlateauRatioVis - 1.0) * std::exp(ExponentInterior));
    3344              :         }
    3345              :     }
    3346              : 
    3347         3386 :     if (screen->bmRefModel == Material::ScreenBeamReflectanceModel::DoNotModel) {
    3348            0 :         if (sunInFront) {
    3349            0 :             tar.BmTrans = Tdirect;
    3350            0 :             tar.BmTransVis = Tdirect;
    3351            0 :             tar.BmTransBack = 0.0;
    3352              :         } else {
    3353            0 :             tar.BmTrans = 0.0;
    3354            0 :             tar.BmTransVis = 0.0;
    3355            0 :             tar.BmTransBack = Tdirect;
    3356              :         }
    3357            0 :         Tscattered = 0.0;
    3358            0 :         TscatteredVis = 0.0;
    3359         3386 :     } else if (screen->bmRefModel == Material::ScreenBeamReflectanceModel::DirectBeam) {
    3360            0 :         if (sunInFront) {
    3361            0 :             tar.BmTrans = Tdirect + Tscattered;
    3362            0 :             tar.BmTransVis = Tdirect + TscatteredVis;
    3363            0 :             tar.BmTransBack = 0.0;
    3364              :         } else {
    3365            0 :             tar.BmTrans = 0.0;
    3366            0 :             tar.BmTransVis = 0.0;
    3367            0 :             tar.BmTransBack = Tdirect + Tscattered;
    3368              :         }
    3369            0 :         Tscattered = 0.0;
    3370            0 :         TscatteredVis = 0.0;
    3371         3386 :     } else if (screen->bmRefModel == Material::ScreenBeamReflectanceModel::Diffuse) {
    3372         3386 :         if (sunInFront) {
    3373         1296 :             tar.BmTrans = Tdirect;
    3374         1296 :             tar.BmTransVis = Tdirect;
    3375         1296 :             tar.BmTransBack = 0.0;
    3376              :         } else {
    3377         2090 :             tar.BmTrans = 0.0;
    3378         2090 :             tar.BmTransVis = 0.0;
    3379         2090 :             tar.BmTransBack = Tdirect;
    3380              :         }
    3381         3386 :         Tscattered = max(0.0, Tscattered);
    3382         3386 :         TscatteredVis = max(0.0, TscatteredVis);
    3383              :     }
    3384              : 
    3385         3386 :     if (sunInFront) {
    3386         1296 :         tar.DfTrans = Tscattered;
    3387         1296 :         tar.DfTransVis = TscatteredVis;
    3388         1296 :         tar.DfTransBack = 0.0;
    3389         1296 :         tar.RefSolFront = max(0.0, ReflCyl * (1.0 - Tdirect) - Tscattered);
    3390         1296 :         tar.RefVisFront = max(0.0, ReflCylVis * (1.0 - Tdirect) - TscatteredVis);
    3391         1296 :         tar.AbsSolFront = max(0.0, (1.0 - Tdirect) * (1.0 - ReflCyl));
    3392         1296 :         tar.RefSolBack = 0.0;
    3393         1296 :         tar.RefVisBack = 0.0;
    3394         1296 :         tar.AbsSolBack = 0.0;
    3395              :     } else {
    3396         2090 :         tar.DfTrans = 0.0;
    3397         2090 :         tar.DfTransVis = 0.0;
    3398         2090 :         tar.DfTransBack = Tscattered;
    3399         2090 :         tar.RefSolFront = 0.0;
    3400         2090 :         tar.RefVisFront = 0.0;
    3401         2090 :         tar.AbsSolFront = 0.0;
    3402         2090 :         tar.RefSolBack = max(0.0, ReflCyl * (1.0 - Tdirect) - Tscattered);
    3403         2090 :         tar.RefVisBack = max(0.0, ReflCylVis * (1.0 - Tdirect) - TscatteredVis);
    3404         2090 :         tar.AbsSolBack = max(0.0, (1.0 - Tdirect) * (1.0 - ReflCyl));
    3405              :     }
    3406         3386 : } // CalcScreenTransmittance()
    3407              : 
    3408            0 : void GetRelativePhiTheta(Real64 phiWin, Real64 thetaWin, Vector3<Real64> const &solcos, Real64 &phi, Real64 &theta)
    3409              : {
    3410            0 :     phi = std::abs(std::acos(solcos.z) - phiWin);
    3411            0 :     theta = std::abs(std::atan2(solcos.x, solcos.y) - thetaWin);
    3412              : 
    3413            0 :     NormalizePhiTheta(phi, theta);
    3414            0 : } // GetRelativePhiTheta()
    3415              : 
    3416              : // Use reflection around Pi to normalize to the range 0 to Pi
    3417         3248 : void NormalizePhiTheta(Real64 &phi, Real64 &theta)
    3418              : {
    3419              : 
    3420         3248 :     while (phi > 2 * Constant::Pi) {
    3421            0 :         phi -= 2 * Constant::Pi;
    3422              :     }
    3423         3248 :     if (phi > Constant::Pi) {
    3424            0 :         phi = 2 * Constant::Pi - phi;
    3425              :     }
    3426              : 
    3427         3724 :     while (theta > 2 * Constant::Pi) {
    3428          476 :         theta -= 2 * Constant::Pi;
    3429              :     }
    3430         3248 :     if (theta > Constant::Pi) {
    3431          812 :         theta = 2 * Constant::Pi - theta;
    3432              :     }
    3433         3248 : } // NormalizePhiTheta()
    3434              : 
    3435         4692 : void GetPhiThetaIndices(Real64 phi, Real64 theta, Real64 dPhi, Real64 dTheta, int &iPhi1, int &iPhi2, int &iTheta1, int &iTheta2)
    3436              : {
    3437         4692 :     iPhi1 = int(phi / dPhi);
    3438         4692 :     iPhi2 = (iPhi1 == maxIPhi - 1) ? iPhi1 : iPhi1 + 1;
    3439         4692 :     iTheta1 = int(theta / dTheta);
    3440         4692 :     iTheta2 = (iTheta1 == maxITheta - 1) ? iTheta1 : iTheta1 + 1;
    3441         4692 : } // GetPhiThetaIndices()
    3442              : 
    3443       561059 : Real64 MaterialBlind::BeamBeamTrans(Real64 const ProfAng, // Solar profile angle (rad)
    3444              :                                     Real64 const SlatAng  // Slat angle (rad)
    3445              : ) const
    3446              : {
    3447              : 
    3448              :     // FUNCTION INFORMATION:
    3449              :     //       AUTHOR         Fred Winkelmann
    3450              :     //       DATE WRITTEN   Jan 2002
    3451              :     //       MODIFIED       na
    3452              :     //       RE-ENGINEERED  na
    3453              : 
    3454              :     // PURPOSE OF THIS SUBROUTINE:
    3455              :     // Calculates beam-to-beam transmittance of a window blind
    3456              : 
    3457              :     // METHODOLOGY EMPLOYED:
    3458              :     // Based on solar profile angle and slat geometry
    3459              : 
    3460       561059 :     Real64 CosProfAng = std::cos(ProfAng); // Cosine of profile angle
    3461       561059 :     Real64 gamma = SlatAng - ProfAng;
    3462       561059 :     Real64 wbar = this->SlatSeparation;
    3463       561059 :     if (CosProfAng != 0.0) {
    3464       561059 :         wbar = this->SlatWidth * std::cos(gamma) / CosProfAng;
    3465              :     }
    3466       561059 :     Real64 BeamBeamTrans = max(0.0, 1.0 - std::abs(wbar / this->SlatSeparation));
    3467              : 
    3468       561059 :     if (BeamBeamTrans > 0.0) {
    3469              : 
    3470              :         // Correction factor that accounts for finite thickness of slats. It is used to modify the
    3471              :         // blind transmittance to account for reflection and absorption by the slat edges.
    3472              :         // fEdge is ratio of area subtended by edge of slat to area between tops of adjacent slats.
    3473              : 
    3474       154986 :         Real64 fEdge = 0.0; // Slat edge correction factor
    3475       154986 :         Real64 fEdge1 = 0.0;
    3476       154986 :         if (std::abs(std::sin(gamma)) > 0.01) {
    3477       154986 :             if ((SlatAng > 0.0 && SlatAng <= Constant::PiOvr2 && ProfAng <= SlatAng) ||
    3478        77142 :                 (SlatAng > Constant::PiOvr2 && SlatAng <= Constant::Pi && ProfAng > -(Constant::Pi - SlatAng))) {
    3479       154986 :                 fEdge1 = this->SlatThickness * std::abs(std::sin(gamma)) /
    3480       154986 :                          ((this->SlatSeparation + this->SlatThickness / std::abs(std::sin(SlatAng))) * CosProfAng);
    3481              :             }
    3482       154986 :             fEdge = min(1.0, std::abs(fEdge1));
    3483              :         }
    3484       154986 :         BeamBeamTrans *= (1.0 - fEdge);
    3485              :     }
    3486              : 
    3487       561059 :     return BeamBeamTrans;
    3488              : 
    3489              : } // MaterialBlind::BeamBeamTrans()
    3490              : 
    3491           27 : void GetProfIndices(Real64 profAng, int &idxLo, int &idxHi)
    3492              : {
    3493           27 :     idxLo = int((profAng + Constant::PiOvr2) / dProfAng) + 1;
    3494           27 :     idxHi = std::min(MaxProfAngs, idxLo + 1);
    3495           27 : }
    3496              : 
    3497        78313 : void GetSlatIndicesInterpFac(Real64 slatAng, int &idxLo, int &idxHi, Real64 &interpFac)
    3498              : {
    3499        78313 :     idxLo = int(slatAng / dSlatAng);
    3500        78313 :     idxHi = std::min(MaxSlatAngs, idxLo + 1);
    3501        78313 :     interpFac = (slatAng - (idxLo * dSlatAng)) / dSlatAng;
    3502        78313 : }
    3503              : 
    3504              : } // namespace EnergyPlus::Material
        

Generated by: LCOV version 2.0-1