Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // 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/DataHeatBalance.hh>
56 : #include <EnergyPlus/DataIPShortCuts.hh>
57 : #include <EnergyPlus/EMSManager.hh>
58 : #include <EnergyPlus/General.hh>
59 : #include <EnergyPlus/GlobalNames.hh>
60 : #include <EnergyPlus/HeatBalanceManager.hh>
61 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
62 : #include <EnergyPlus/Material.hh>
63 : #include <EnergyPlus/ScheduleManager.hh>
64 : #include <EnergyPlus/UtilityRoutines.hh>
65 :
66 : namespace EnergyPlus::Material {
67 :
68 : constexpr std::array<std::string_view, (int)GapVentType::Num> gapVentTypeNames = {"Sealed", "VentedIndoor", "VentedOutdoor"};
69 : constexpr std::array<std::string_view, (int)GasType::Num> gasTypeNames = {"Custom", "Air", "Argon", "Krypton", "Xenon"};
70 : constexpr std::array<std::string_view, (int)GasType::Num> gasTypeNamesUC = {"CUSTOM", "AIR", "ARGON", "KRYPTON", "XENON"};
71 : constexpr std::array<std::string_view, (int)SurfaceRoughness::Num> surfaceRoughnessNames = {
72 : "VeryRough", "Rough", "MediumRough", "MediumSmooth", "Smooth", "VerySmooth"};
73 :
74 : constexpr std::array<Material::Gas, 10> gases = {
75 : Gas(), // Empty
76 : {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
77 : {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
78 : {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
79 : {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
80 : Gas(), // Empty
81 : Gas(), // Empty
82 : Gas(), // Empty
83 : Gas(), // Empty
84 : Gas() // Empty
85 : };
86 :
87 796 : void GetMaterialData(EnergyPlusData &state, bool &ErrorsFound) // set to true if errors found in input
88 : {
89 :
90 : // SUBROUTINE INFORMATION:
91 : // AUTHOR Richard Liesen
92 : // DATE WRITTEN September 1997
93 : // MODIFIED April 1999; L.Lawrie
94 : // Sept 1999, FCW, Window5 modifications
95 : // Mar 2001, FCW, WindowShade mods
96 : // Sep 2001, FCW, add Material:WindowGasMixture
97 : // Oct 2001, FCW, add Material:WindowBlind
98 : // Dec 2003, FCW, add glass solar/visible transmittance dirt factor
99 : // Feb 2009, TH, added WindowMaterial:GlazingGroup:Thermochromic
100 :
101 : // RE-ENGINEERED na
102 :
103 : // PURPOSE OF THIS SUBROUTINE:
104 : // The purpose of this subroutine is to serve as a transfer agent
105 : // between the input file and the material derived type. The new input
106 : // file is working, and this file reads the material data directly
107 : // from the input file and transfer that information to the new data
108 : // structure. Data read in this routine is stored in a
109 : // derived type (Material) defined in the DataHeatBalance module.
110 :
111 : // In April 1999, a new set of material definitions replaced the one "all-purpose"
112 : // material definition. There are now 10 flavors of materials. Definitions from
113 : // the IDD appear below before their counterpart "gets".
114 :
115 : using Curve::GetCurveIndex;
116 : using Curve::GetCurveMinMaxValues;
117 :
118 : using General::ScanForReports;
119 :
120 : // if this has a size, then input has already been gotten
121 796 : if (state.dataHeatBalMgr->UniqueMaterialNames.size()) {
122 0 : return;
123 : }
124 :
125 : int IOStat; // IO Status when calling get input subroutine
126 796 : Array1D_string MaterialNames(7); // Number of Material Alpha names defined
127 : int MaterNum; // Counter to keep track of the material number
128 : int MaterialNumAlpha; // Number of material alpha names being passed
129 : int MaterialNumProp; // Number of material properties being passed
130 796 : Array1D<Real64> MaterialProps(27); // Temporary array to transfer material properties
131 : int RegMat; // Regular Materials -- full property definition
132 : int RegRMat; // Regular Materials -- R only property definition
133 : int AirMat; // Air space materials in opaque constructions
134 : int IRTMat; // Infrared Transmitting Materials -- R only property definition
135 :
136 : int EcoRoofMat; // Materials for ecoRoof
137 : int NumGas; // Index for loop over gap gases in a mixture
138 : int NumGases; // Number of gasses in a mixture
139 796 : GasType gasType = GasType::Invalid; // Gas type index: 1=air, 2=argon, 3=krypton, 4=xenon
140 : int Loop;
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 796 : int iTC(0);
157 796 : int iMat(0);
158 :
159 : // Added TH 7/27/2009 for constructions defined with F or C factor method
160 : int TotFfactorConstructs; // Number of slabs-on-grade or underground floor constructions defined with F factors
161 : int TotCfactorConstructs; // Number of underground wall constructions defined with C factors
162 :
163 : static constexpr std::string_view RoutineName("GetMaterialData: ");
164 :
165 796 : auto &ip = state.dataInputProcessing->inputProcessor;
166 796 : auto &ipsc = state.dataIPShortCut;
167 :
168 796 : RegMat = ip->getNumObjectsFound(state, "Material");
169 796 : RegRMat = ip->getNumObjectsFound(state, "Material:NoMass");
170 796 : IRTMat = ip->getNumObjectsFound(state, "Material:InfraredTransparent");
171 796 : AirMat = ip->getNumObjectsFound(state, "Material:AirGap");
172 796 : state.dataHeatBal->W5GlsMat = ip->getNumObjectsFound(state, "WindowMaterial:Glazing");
173 796 : state.dataHeatBal->W5GlsMatAlt = ip->getNumObjectsFound(state, "WindowMaterial:Glazing:RefractionExtinctionMethod");
174 796 : state.dataHeatBal->W5GasMat = ip->getNumObjectsFound(state, "WindowMaterial:Gas");
175 796 : state.dataHeatBal->W5GasMatMixture = ip->getNumObjectsFound(state, "WindowMaterial:GasMixture");
176 796 : state.dataHeatBal->TotShades = ip->getNumObjectsFound(state, "WindowMaterial:Shade");
177 796 : state.dataMaterial->TotComplexShades = ip->getNumObjectsFound(state, "WindowMaterial:ComplexShade");
178 796 : state.dataHeatBal->TotComplexGaps = ip->getNumObjectsFound(state, "WindowMaterial:Gap");
179 796 : state.dataHeatBal->TotScreens = ip->getNumObjectsFound(state, "WindowMaterial:Screen");
180 796 : state.dataHeatBal->TotBlinds = ip->getNumObjectsFound(state, "WindowMaterial:Blind");
181 796 : EcoRoofMat = ip->getNumObjectsFound(state, "Material:RoofVegetation");
182 796 : state.dataHeatBal->TotSimpleWindow = ip->getNumObjectsFound(state, "WindowMaterial:SimpleGlazingSystem");
183 :
184 796 : state.dataHeatBal->W5GlsMatEQL = ip->getNumObjectsFound(state, "WindowMaterial:Glazing:EquivalentLayer");
185 796 : state.dataHeatBal->TotShadesEQL = ip->getNumObjectsFound(state, "WindowMaterial:Shade:EquivalentLayer");
186 796 : state.dataHeatBal->TotDrapesEQL = ip->getNumObjectsFound(state, "WindowMaterial:Drape:EquivalentLayer");
187 796 : state.dataHeatBal->TotBlindsEQL = ip->getNumObjectsFound(state, "WindowMaterial:Blind:EquivalentLayer");
188 796 : state.dataHeatBal->TotScreensEQL = ip->getNumObjectsFound(state, "WindowMaterial:Screen:EquivalentLayer");
189 796 : state.dataHeatBal->W5GapMatEQL = ip->getNumObjectsFound(state, "WindowMaterial:Gap:EquivalentLayer");
190 :
191 796 : state.dataMaterial->TotMaterials = RegMat + RegRMat + AirMat + state.dataHeatBal->W5GlsMat + state.dataHeatBal->W5GlsMatAlt +
192 796 : state.dataHeatBal->W5GasMat + state.dataHeatBal->W5GasMatMixture + state.dataHeatBal->TotShades +
193 796 : state.dataHeatBal->TotScreens + state.dataHeatBal->TotBlinds + EcoRoofMat + IRTMat +
194 796 : state.dataHeatBal->TotSimpleWindow + state.dataMaterial->TotComplexShades + state.dataHeatBal->TotComplexGaps +
195 796 : state.dataHeatBal->W5GlsMatEQL + state.dataHeatBal->TotShadesEQL + state.dataHeatBal->TotDrapesEQL +
196 796 : state.dataHeatBal->TotBlindsEQL + state.dataHeatBal->TotScreensEQL + state.dataHeatBal->W5GapMatEQL;
197 :
198 796 : TotFfactorConstructs = ip->getNumObjectsFound(state, "Construction:FfactorGroundFloor");
199 796 : TotCfactorConstructs = ip->getNumObjectsFound(state, "Construction:CfactorUndergroundWall");
200 :
201 796 : if (TotFfactorConstructs > 0) {
202 15 : state.dataHeatBal->NoFfactorConstructionsUsed = false;
203 : }
204 :
205 796 : if (TotCfactorConstructs > 0) {
206 7 : state.dataHeatBal->NoCfactorConstructionsUsed = false;
207 : }
208 :
209 796 : if (TotFfactorConstructs + TotCfactorConstructs >= 1) {
210 : // Add a new fictitious insulation layer and a thermal mass layer for each F or C factor defined construction
211 21 : state.dataMaterial->TotMaterials += 1 + TotFfactorConstructs + TotCfactorConstructs;
212 : }
213 :
214 : // yujie: This looks kind of silly, but we need it to keep the Materials array in IDF order.
215 14714 : for (int i = 1; i <= state.dataMaterial->TotMaterials; i++) {
216 13918 : MaterialBase *p = new MaterialBase;
217 13918 : state.dataMaterial->Material.push_back(p);
218 : }
219 796 : state.dataHeatBalMgr->UniqueMaterialNames.reserve(static_cast<unsigned>(state.dataMaterial->TotMaterials));
220 :
221 796 : state.dataHeatBal->NominalR.dimension(state.dataMaterial->TotMaterials, 0.0);
222 :
223 796 : MaterNum = 0;
224 :
225 : // Regular Materials
226 :
227 796 : state.dataHeatBalMgr->CurrentModuleObject = "Material";
228 796 : auto const instances = ip->epJSON.find(state.dataHeatBalMgr->CurrentModuleObject);
229 796 : if (instances != ip->epJSON.end()) {
230 763 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, state.dataHeatBalMgr->CurrentModuleObject);
231 :
232 763 : int counter = 0;
233 763 : auto &instancesValue = instances.value();
234 9361 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
235 8598 : auto const &objectFields = instance.value();
236 8598 : std::string const &thisObjectName = Util::makeUPPER(instance.key());
237 8598 : ip->markObjectAsUsed(state.dataHeatBalMgr->CurrentModuleObject, instance.key());
238 8598 : std::string materialName = thisObjectName;
239 :
240 17196 : if (GlobalNames::VerifyUniqueInterObjectName(state,
241 8598 : state.dataHeatBalMgr->UniqueMaterialNames,
242 : materialName,
243 8598 : state.dataHeatBalMgr->CurrentModuleObject,
244 8598 : ipsc->cAlphaFieldNames(1),
245 : ErrorsFound)) {
246 0 : continue;
247 : }
248 : // For incoming idf, maintain object order
249 8598 : ++counter;
250 8598 : MaterNum = ip->getIDFObjNum(state, state.dataHeatBalMgr->CurrentModuleObject, counter);
251 :
252 : // Load the material derived type from the input data.
253 8598 : auto *thisMaterial = new MaterialChild;
254 8598 : state.dataMaterial->Material(MaterNum) = thisMaterial;
255 8598 : thisMaterial->group = Group::Regular;
256 8598 : thisMaterial->Name = materialName;
257 :
258 17196 : std::string roughness = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "roughness");
259 8598 : thisMaterial->Roughness = static_cast<SurfaceRoughness>(getEnumValue(surfaceRoughnessNamesUC, Util::makeUPPER(roughness)));
260 8598 : thisMaterial->Thickness = ip->getRealFieldValue(objectFields, objectSchemaProps, "thickness");
261 8598 : thisMaterial->Conductivity = ip->getRealFieldValue(objectFields, objectSchemaProps, "conductivity");
262 8598 : thisMaterial->Density = ip->getRealFieldValue(objectFields, objectSchemaProps, "density");
263 8598 : thisMaterial->SpecHeat = ip->getRealFieldValue(objectFields, objectSchemaProps, "specific_heat");
264 8598 : thisMaterial->AbsorpThermal = ip->getRealFieldValue(objectFields, objectSchemaProps, "thermal_absorptance");
265 8598 : thisMaterial->AbsorpThermalInput = thisMaterial->AbsorpThermal;
266 8598 : thisMaterial->AbsorpSolar = ip->getRealFieldValue(objectFields, objectSchemaProps, "solar_absorptance");
267 8598 : thisMaterial->AbsorpSolarInput = thisMaterial->AbsorpSolar;
268 8598 : thisMaterial->AbsorpVisible = ip->getRealFieldValue(objectFields, objectSchemaProps, "visible_absorptance");
269 8598 : thisMaterial->AbsorpVisibleInput = thisMaterial->AbsorpVisible;
270 :
271 8598 : if (thisMaterial->Conductivity > 0.0) {
272 8598 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Thickness / thisMaterial->Conductivity;
273 8598 : thisMaterial->Resistance = state.dataHeatBal->NominalR(MaterNum);
274 : } else {
275 0 : ShowSevereError(state, format("Positive thermal conductivity required for material {}", thisMaterial->Name));
276 0 : ErrorsFound = true;
277 : }
278 9361 : }
279 763 : MaterNum = counter; // This works here, because this is the first material type processed
280 : }
281 : // Add the 6" heavy concrete for constructions defined with F or C factor method
282 796 : if (TotFfactorConstructs + TotCfactorConstructs >= 1) {
283 21 : ++MaterNum;
284 21 : auto *thisMaterial = new MaterialChild;
285 21 : state.dataMaterial->Material(MaterNum) = thisMaterial;
286 21 : thisMaterial->group = Group::Regular;
287 21 : thisMaterial->Name = "~FC_Concrete";
288 21 : thisMaterial->Thickness = 0.15; // m, 0.15m = 6 inches
289 21 : thisMaterial->Conductivity = 1.95; // W/mK
290 21 : thisMaterial->Density = 2240.0; // kg/m3
291 21 : thisMaterial->SpecHeat = 900.0; // J/kgK
292 21 : thisMaterial->Roughness = SurfaceRoughness::MediumRough;
293 21 : thisMaterial->AbsorpSolar = 0.7;
294 21 : thisMaterial->AbsorpThermal = 0.9;
295 21 : thisMaterial->AbsorpVisible = 0.7;
296 21 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Thickness / thisMaterial->Conductivity;
297 21 : thisMaterial->Resistance = state.dataHeatBal->NominalR(MaterNum);
298 :
299 21 : ++RegMat;
300 : }
301 :
302 796 : state.dataHeatBalMgr->CurrentModuleObject = "Material:NoMass";
303 2586 : for (Loop = 1; Loop <= RegRMat; ++Loop) {
304 :
305 : // Call Input Get routine to retrieve material data
306 5370 : ip->getObjectItem(state,
307 1790 : state.dataHeatBalMgr->CurrentModuleObject,
308 : Loop,
309 : MaterialNames,
310 : MaterialNumAlpha,
311 : MaterialProps,
312 : MaterialNumProp,
313 : IOStat,
314 1790 : ipsc->lNumericFieldBlanks,
315 1790 : ipsc->lAlphaFieldBlanks,
316 1790 : ipsc->cAlphaFieldNames,
317 1790 : ipsc->cNumericFieldNames);
318 3580 : if (GlobalNames::VerifyUniqueInterObjectName(state,
319 1790 : state.dataHeatBalMgr->UniqueMaterialNames,
320 1790 : MaterialNames(1),
321 1790 : state.dataHeatBalMgr->CurrentModuleObject,
322 1790 : ipsc->cAlphaFieldNames(1),
323 : ErrorsFound)) {
324 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
325 0 : continue;
326 : }
327 :
328 : // Load the material derived type from the input data.
329 1790 : ++MaterNum;
330 1790 : auto *thisMaterial = new MaterialChild;
331 1790 : state.dataMaterial->Material(MaterNum) = thisMaterial;
332 1790 : thisMaterial->group = Group::Regular;
333 1790 : thisMaterial->Name = MaterialNames(1);
334 :
335 1790 : thisMaterial->Roughness = static_cast<SurfaceRoughness>(getEnumValue(surfaceRoughnessNamesUC, Util::makeUPPER(MaterialNames(2))));
336 :
337 1790 : thisMaterial->Resistance = MaterialProps(1);
338 1790 : thisMaterial->ROnly = true;
339 1790 : if (MaterialNumProp >= 2) {
340 1653 : thisMaterial->AbsorpThermal = MaterialProps(2);
341 1653 : thisMaterial->AbsorpThermalInput = MaterialProps(2);
342 : } else {
343 137 : thisMaterial->AbsorpThermal = 0.9;
344 137 : thisMaterial->AbsorpThermalInput = 0.9;
345 : }
346 1790 : if (MaterialNumProp >= 3) {
347 1653 : thisMaterial->AbsorpSolar = MaterialProps(3);
348 1653 : thisMaterial->AbsorpSolarInput = MaterialProps(3);
349 : } else {
350 137 : thisMaterial->AbsorpSolar = 0.7;
351 137 : thisMaterial->AbsorpSolarInput = 0.7;
352 : }
353 1790 : if (MaterialNumProp >= 4) {
354 1549 : thisMaterial->AbsorpVisible = MaterialProps(4);
355 1549 : thisMaterial->AbsorpVisibleInput = MaterialProps(4);
356 : } else {
357 241 : thisMaterial->AbsorpVisible = 0.7;
358 241 : thisMaterial->AbsorpVisibleInput = 0.7;
359 : }
360 :
361 1790 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Resistance;
362 : }
363 :
364 : // Add a fictitious insulation layer for each construction defined with F or C factor method
365 796 : if (TotFfactorConstructs + TotCfactorConstructs >= 1) {
366 238 : for (Loop = 1; Loop <= TotFfactorConstructs + TotCfactorConstructs; ++Loop) {
367 217 : ++MaterNum;
368 217 : auto *thisMaterial = new MaterialChild;
369 217 : state.dataMaterial->Material(MaterNum) = thisMaterial;
370 217 : thisMaterial->group = Group::Regular;
371 217 : thisMaterial->Name = format("~FC_Insulation_{}", Loop);
372 217 : thisMaterial->ROnly = true;
373 217 : thisMaterial->Roughness = SurfaceRoughness::MediumRough;
374 217 : thisMaterial->AbsorpSolar = 0.0;
375 217 : thisMaterial->AbsorpThermal = 0.0;
376 217 : thisMaterial->AbsorpVisible = 0.0;
377 : }
378 21 : RegRMat += TotFfactorConstructs + TotCfactorConstructs;
379 : }
380 :
381 : // Air Materials (for air spaces in opaque constructions)
382 796 : state.dataHeatBalMgr->CurrentModuleObject = "Material:AirGap";
383 1338 : for (Loop = 1; Loop <= AirMat; ++Loop) {
384 :
385 : // Call Input Get routine to retrieve material data
386 1626 : ip->getObjectItem(state,
387 542 : state.dataHeatBalMgr->CurrentModuleObject,
388 : Loop,
389 : MaterialNames,
390 : MaterialNumAlpha,
391 : MaterialProps,
392 : MaterialNumProp,
393 : IOStat,
394 542 : ipsc->lNumericFieldBlanks,
395 542 : ipsc->lAlphaFieldBlanks,
396 542 : ipsc->cAlphaFieldNames,
397 542 : ipsc->cNumericFieldNames);
398 1084 : if (GlobalNames::VerifyUniqueInterObjectName(state,
399 542 : state.dataHeatBalMgr->UniqueMaterialNames,
400 542 : MaterialNames(1),
401 542 : state.dataHeatBalMgr->CurrentModuleObject,
402 542 : ipsc->cAlphaFieldNames(1),
403 : ErrorsFound)) {
404 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
405 0 : continue;
406 : }
407 :
408 : // Load the material derived type from the input data.
409 542 : ++MaterNum;
410 542 : auto *thisMaterial = new MaterialChild;
411 542 : state.dataMaterial->Material(MaterNum) = thisMaterial;
412 542 : thisMaterial->group = Group::Air;
413 542 : thisMaterial->Name = MaterialNames(1);
414 :
415 542 : thisMaterial->Roughness = SurfaceRoughness::MediumRough;
416 :
417 542 : thisMaterial->Resistance = MaterialProps(1);
418 542 : thisMaterial->ROnly = true;
419 :
420 542 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Resistance;
421 : }
422 :
423 796 : state.dataHeatBalMgr->CurrentModuleObject = "Material:InfraredTransparent";
424 799 : for (Loop = 1; Loop <= IRTMat; ++Loop) {
425 :
426 : // Call Input Get routine to retrieve material data
427 9 : ip->getObjectItem(state,
428 3 : state.dataHeatBalMgr->CurrentModuleObject,
429 : Loop,
430 : MaterialNames,
431 : MaterialNumAlpha,
432 : MaterialProps,
433 : MaterialNumProp,
434 : IOStat,
435 3 : ipsc->lNumericFieldBlanks,
436 3 : ipsc->lAlphaFieldBlanks,
437 3 : ipsc->cAlphaFieldNames,
438 3 : ipsc->cNumericFieldNames);
439 6 : if (GlobalNames::VerifyUniqueInterObjectName(state,
440 3 : state.dataHeatBalMgr->UniqueMaterialNames,
441 3 : MaterialNames(1),
442 3 : state.dataHeatBalMgr->CurrentModuleObject,
443 3 : ipsc->cAlphaFieldNames(1),
444 : ErrorsFound)) {
445 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
446 0 : continue;
447 : }
448 :
449 3 : ++MaterNum;
450 3 : auto *thisMaterial = new MaterialChild;
451 3 : state.dataMaterial->Material(MaterNum) = thisMaterial;
452 3 : thisMaterial->group = Group::IRTransparent;
453 :
454 : // Load the material derived type from the input data.
455 3 : thisMaterial->Name = MaterialNames(1);
456 :
457 : // Load data for other properties that need defaults
458 3 : thisMaterial->ROnly = true;
459 3 : thisMaterial->Resistance = 0.01;
460 3 : thisMaterial->AbsorpThermal = 0.9999;
461 3 : thisMaterial->AbsorpThermalInput = 0.9999;
462 3 : thisMaterial->AbsorpSolar = 1.0;
463 3 : thisMaterial->AbsorpSolarInput = 1.0;
464 3 : thisMaterial->AbsorpVisible = 1.0;
465 3 : thisMaterial->AbsorpVisibleInput = 1.0;
466 :
467 3 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Resistance;
468 : }
469 :
470 : // Glass materials, regular input: transmittance and front/back reflectance
471 :
472 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Glazing";
473 2509 : for (Loop = 1; Loop <= state.dataHeatBal->W5GlsMat; ++Loop) {
474 :
475 : // Call Input Get routine to retrieve material data
476 5139 : ip->getObjectItem(state,
477 1713 : state.dataHeatBalMgr->CurrentModuleObject,
478 : Loop,
479 : MaterialNames,
480 : MaterialNumAlpha,
481 : MaterialProps,
482 : MaterialNumProp,
483 : IOStat,
484 1713 : ipsc->lNumericFieldBlanks,
485 1713 : ipsc->lAlphaFieldBlanks,
486 1713 : ipsc->cAlphaFieldNames,
487 1713 : ipsc->cNumericFieldNames);
488 3426 : if (GlobalNames::VerifyUniqueInterObjectName(state,
489 1713 : state.dataHeatBalMgr->UniqueMaterialNames,
490 1713 : MaterialNames(1),
491 1713 : state.dataHeatBalMgr->CurrentModuleObject,
492 1713 : ipsc->cAlphaFieldNames(1),
493 : ErrorsFound)) {
494 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
495 0 : continue;
496 : }
497 :
498 1713 : ++MaterNum;
499 1713 : auto *thisMaterial = new MaterialChild;
500 1713 : state.dataMaterial->Material(MaterNum) = thisMaterial;
501 1713 : thisMaterial->group = Group::WindowGlass;
502 :
503 : // Load the material derived type from the input data.
504 :
505 1713 : thisMaterial->Name = MaterialNames(1);
506 1713 : thisMaterial->Roughness = SurfaceRoughness::VerySmooth;
507 1713 : thisMaterial->ROnly = true;
508 1713 : thisMaterial->Thickness = MaterialProps(1);
509 1713 : if (!Util::SameString(MaterialNames(2), "SpectralAndAngle")) {
510 1712 : thisMaterial->Trans = MaterialProps(2);
511 1712 : thisMaterial->ReflectSolBeamFront = MaterialProps(3);
512 1712 : thisMaterial->ReflectSolBeamBack = MaterialProps(4);
513 1712 : thisMaterial->TransVis = MaterialProps(5);
514 1712 : thisMaterial->ReflectVisBeamFront = MaterialProps(6);
515 1712 : thisMaterial->ReflectVisBeamBack = MaterialProps(7);
516 1712 : thisMaterial->TransThermal = MaterialProps(8);
517 : }
518 1713 : thisMaterial->AbsorpThermalFront = MaterialProps(9);
519 1713 : thisMaterial->AbsorpThermalBack = MaterialProps(10);
520 1713 : thisMaterial->Conductivity = MaterialProps(11);
521 1713 : thisMaterial->GlassTransDirtFactor = MaterialProps(12);
522 1713 : thisMaterial->YoungModulus = MaterialProps(13);
523 1713 : thisMaterial->PoissonsRatio = MaterialProps(14);
524 1713 : if (MaterialProps(12) == 0.0) thisMaterial->GlassTransDirtFactor = 1.0;
525 1713 : thisMaterial->AbsorpThermal = thisMaterial->AbsorpThermalBack;
526 :
527 1713 : if (thisMaterial->Conductivity > 0.0) {
528 1713 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Thickness / thisMaterial->Conductivity;
529 1713 : thisMaterial->Resistance = state.dataHeatBal->NominalR(MaterNum);
530 : } else {
531 0 : ErrorsFound = true;
532 0 : ShowSevereError(state, format("Window glass material {} has Conductivity = 0.0, must be >0.0, default = .9", thisMaterial->Name));
533 : }
534 :
535 1713 : thisMaterial->GlassSpectralDataPtr = 0;
536 1713 : if (state.dataHeatBal->TotSpectralData > 0 && !ipsc->lAlphaFieldBlanks(3)) {
537 83 : thisMaterial->GlassSpectralDataPtr = Util::FindItemInList(MaterialNames(3), state.dataHeatBal->SpectralData);
538 : }
539 1713 : if (Util::SameString(MaterialNames(2), "SpectralAverage")) thisMaterial->GlassSpectralDataPtr = 0;
540 : // No need for spectral data for BSDF either
541 1713 : if (Util::SameString(MaterialNames(2), "BSDF")) thisMaterial->GlassSpectralDataPtr = 0;
542 1713 : if (Util::SameString(MaterialNames(2), "SpectralAndAngle")) thisMaterial->GlassSpectralAndAngle = true;
543 :
544 1713 : if (thisMaterial->GlassSpectralDataPtr == 0 && Util::SameString(MaterialNames(2), "Spectral")) {
545 0 : ErrorsFound = true;
546 0 : ShowSevereError(state,
547 0 : format("{}=\"{}\" has {} = Spectral but has no matching MaterialProperty:GlazingSpectralData set",
548 0 : state.dataHeatBalMgr->CurrentModuleObject,
549 0 : thisMaterial->Name,
550 0 : ipsc->cAlphaFieldNames(2)));
551 0 : if (ipsc->lAlphaFieldBlanks(3)) {
552 0 : ShowContinueError(state, format("...{} is blank.", ipsc->cAlphaFieldNames(3)));
553 : } else {
554 0 : ShowContinueError(state,
555 0 : format("...{}=\"{}\" not found as item in MaterialProperty:GlazingSpectralData objects.",
556 0 : ipsc->cAlphaFieldNames(3),
557 : MaterialNames(3)));
558 : }
559 : }
560 :
561 1813 : if (!Util::SameString(MaterialNames(2), "SpectralAverage") && !Util::SameString(MaterialNames(2), "Spectral") &&
562 1813 : !Util::SameString(MaterialNames(2), "BSDF") && !Util::SameString(MaterialNames(2), "SpectralAndAngle")) {
563 0 : ErrorsFound = true;
564 0 : ShowSevereError(state, format("{}=\"{}\", invalid specification.", state.dataHeatBalMgr->CurrentModuleObject, thisMaterial->Name));
565 0 : ShowContinueError(
566 : state,
567 0 : format("{} must be SpectralAverage, Spectral, BSDF or SpectralAndAngle, value={}", ipsc->cAlphaFieldNames(2), MaterialNames(2)));
568 : }
569 :
570 : // TH 8/24/2011, allow glazing properties MaterialProps(2 to 10) to equal 0 or 1: 0.0 =< Prop <= 1.0
571 : // Fixed CR 8413 - modeling spandrel panels as glazing systems
572 1713 : if (Util::SameString(MaterialNames(2), "SpectralAverage")) {
573 :
574 1613 : if (MaterialProps(2) + MaterialProps(3) > 1.0) {
575 0 : ErrorsFound = true;
576 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
577 0 : ShowContinueError(state, format("{} + {} not <= 1.0", ipsc->cNumericFieldNames(2), ipsc->cNumericFieldNames(3)));
578 : }
579 :
580 1613 : if (MaterialProps(2) + MaterialProps(4) > 1.0) {
581 0 : ErrorsFound = true;
582 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
583 0 : ShowContinueError(state, format("{} + {} not <= 1.0", ipsc->cNumericFieldNames(2), ipsc->cNumericFieldNames(4)));
584 : }
585 :
586 1613 : if (MaterialProps(5) + MaterialProps(6) > 1.0) {
587 0 : ErrorsFound = true;
588 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
589 0 : ShowContinueError(state, format("{} + {} not <= 1.0", ipsc->cNumericFieldNames(5), ipsc->cNumericFieldNames(6)));
590 : }
591 :
592 1613 : if (MaterialProps(5) + MaterialProps(7) > 1.0) {
593 0 : ErrorsFound = true;
594 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
595 0 : ShowContinueError(state, format("{} + {} not <= 1.0", ipsc->cNumericFieldNames(5), ipsc->cNumericFieldNames(7)));
596 : }
597 :
598 1613 : if (MaterialProps(8) + MaterialProps(9) > 1.0) {
599 0 : ErrorsFound = true;
600 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
601 0 : ShowContinueError(state, format("{} + {} not <= 1.0", ipsc->cNumericFieldNames(8), ipsc->cNumericFieldNames(9)));
602 : }
603 :
604 1613 : if (MaterialProps(8) + MaterialProps(10) > 1.0) {
605 0 : ErrorsFound = true;
606 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
607 0 : ShowContinueError(state, format("{} + {} not <= 1.0", ipsc->cNumericFieldNames(8), ipsc->cNumericFieldNames(10)));
608 : }
609 :
610 1613 : if (MaterialProps(2) < 0.0) {
611 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
612 0 : ShowContinueError(state, format("{} not >= 0.0", ipsc->cNumericFieldNames(2)));
613 0 : ErrorsFound = true;
614 : }
615 :
616 1613 : if (MaterialProps(2) > 1.0) {
617 0 : ErrorsFound = true;
618 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
619 0 : ShowContinueError(state, format("{} not <= 1.0", ipsc->cNumericFieldNames(2)));
620 : }
621 :
622 1613 : if (MaterialProps(3) < 0.0 || MaterialProps(3) > 1.0) {
623 0 : ErrorsFound = true;
624 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
625 0 : ShowContinueError(state, format("{} not >= 0.0 and <= 1.0", ipsc->cNumericFieldNames(3)));
626 : }
627 :
628 1613 : if (MaterialProps(4) < 0.0 || MaterialProps(4) > 1.0) {
629 0 : ErrorsFound = true;
630 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
631 0 : ShowContinueError(state, format("{} not >= 0.0 and <= 1.0", ipsc->cNumericFieldNames(4)));
632 : }
633 :
634 1613 : if (MaterialProps(5) < 0.0) {
635 0 : ShowWarningError(state, format("{}=\"{}\", minimal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
636 0 : ShowWarningError(state, format("{} not >= 0.0", ipsc->cNumericFieldNames(5)));
637 : }
638 :
639 1613 : if (MaterialProps(5) > 1.0) {
640 0 : ErrorsFound = true;
641 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
642 0 : ShowContinueError(state, format("{} not <= 1.0", ipsc->cNumericFieldNames(5)));
643 : }
644 :
645 1613 : if (MaterialProps(6) < 0.0 || MaterialProps(6) > 1.0) {
646 0 : ErrorsFound = true;
647 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
648 0 : ShowContinueError(state, format("{} not >= 0.0 and <= 1.0", ipsc->cNumericFieldNames(6)));
649 : }
650 :
651 1613 : if (MaterialProps(7) < 0.0 || MaterialProps(7) > 1.0) {
652 0 : ErrorsFound = true;
653 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
654 0 : ShowContinueError(state, format("{} not >= 0.0 and <= 1.0", ipsc->cNumericFieldNames(7)));
655 : }
656 : }
657 :
658 1713 : if (MaterialProps(8) > 1.0) {
659 0 : ErrorsFound = true;
660 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
661 0 : ShowContinueError(state, format("{} not <= 1.0", ipsc->cNumericFieldNames(8)));
662 : }
663 :
664 1713 : if (MaterialProps(9) <= 0.0 || MaterialProps(9) >= 1.0) {
665 0 : ErrorsFound = true;
666 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
667 0 : ShowContinueError(state, format("{} not > 0.0 and < 1.0", ipsc->cNumericFieldNames(9)));
668 : }
669 :
670 1713 : if (MaterialProps(10) <= 0.0 || MaterialProps(10) >= 1.0) {
671 0 : ErrorsFound = true;
672 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
673 0 : ShowContinueError(state, format("{} not > 0.0 and < 1.0", ipsc->cNumericFieldNames(10)));
674 : }
675 :
676 1713 : if (MaterialProps(11) <= 0.0) {
677 0 : ErrorsFound = true;
678 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
679 0 : ShowContinueError(state, format("{} not > 0.0", ipsc->cNumericFieldNames(11)));
680 : }
681 :
682 1713 : if (MaterialProps(13) < 0.0) {
683 0 : ErrorsFound = true;
684 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
685 0 : ShowContinueError(state, format("{} not > 0.0", ipsc->cNumericFieldNames(13)));
686 : }
687 :
688 1713 : if (MaterialProps(14) < 0.0 || MaterialProps(14) >= 1.0) {
689 0 : ErrorsFound = true;
690 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
691 0 : ShowContinueError(state, format("{} not > 0.0 and < 1.0", ipsc->cNumericFieldNames(14)));
692 : }
693 :
694 1713 : if (MaterialNames(4) == "") {
695 0 : thisMaterial->SolarDiffusing = false;
696 : } else {
697 1713 : BooleanSwitch answer = getYesNoValue(MaterialNames(4));
698 1713 : if (answer == BooleanSwitch::Invalid) {
699 0 : ErrorsFound = true;
700 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
701 0 : ShowContinueError(state, format("{} must be Yes or No, entered value={}", ipsc->cNumericFieldNames(4), MaterialNames(4)));
702 : } else {
703 1713 : thisMaterial->SolarDiffusing = (answer == BooleanSwitch::Yes);
704 : }
705 : }
706 : // Get SpectralAndAngle table names
707 1713 : if (thisMaterial->GlassSpectralAndAngle) {
708 1 : if (ipsc->lAlphaFieldBlanks(5)) {
709 0 : ErrorsFound = true;
710 0 : ShowSevereError(state, format("{}=\"{}\", blank field.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
711 0 : ShowContinueError(state, " Table name must be entered when the key SpectralAndAngle is selected as Optical Data Type.");
712 : } else {
713 1 : thisMaterial->GlassSpecAngTransDataPtr = Curve::GetCurveIndex(state, MaterialNames(5));
714 1 : if (thisMaterial->GlassSpecAngTransDataPtr == 0) {
715 0 : ErrorsFound = true;
716 0 : ShowSevereError(state, format("{}=\"{}\", Invalid name.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
717 0 : ShowContinueError(state,
718 0 : format("{} requires a valid table object name, entered input={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
719 : } else {
720 2 : ErrorsFound |= Curve::CheckCurveDims(state,
721 : thisMaterial->GlassSpecAngTransDataPtr, // Curve index
722 : {2}, // Valid dimensions
723 : RoutineName, // Routine name
724 1 : state.dataHeatBalMgr->CurrentModuleObject, // Object Type
725 : thisMaterial->Name, // Object Name
726 1 : ipsc->cAlphaFieldNames(5)); // Field Name
727 :
728 1 : GetCurveMinMaxValues(state, thisMaterial->GlassSpecAngTransDataPtr, minAngValue, maxAngValue, minLamValue, maxLamValue);
729 1 : if (minAngValue > 1.0e-6) {
730 0 : ErrorsFound = true;
731 0 : ShowSevereError(state,
732 0 : format("{}=\"{}\", Invalid minimum value of angle = {:.2R}.",
733 0 : state.dataHeatBalMgr->CurrentModuleObject,
734 : MaterialNames(1),
735 : minAngValue));
736 0 : ShowContinueError(
737 : state,
738 0 : format("{} requires the minumum value = 0.0 in the entered table name={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
739 : }
740 1 : if (std::abs(maxAngValue - 90.0) > 1.0e-6) {
741 0 : ErrorsFound = true;
742 0 : ShowSevereError(state,
743 0 : format("{}=\"{}\", Invalid maximum value of angle = {:.2R}.",
744 0 : state.dataHeatBalMgr->CurrentModuleObject,
745 : MaterialNames(1),
746 : maxAngValue));
747 0 : ShowContinueError(
748 : state,
749 0 : format("{} requires the maximum value = 90.0 in the entered table name={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
750 : }
751 1 : if (minLamValue < 0.1) {
752 0 : ErrorsFound = true;
753 0 : ShowSevereError(state,
754 0 : format("{}=\"{}\", Invalid minimum value of wavelength = {:.2R}.",
755 0 : state.dataHeatBalMgr->CurrentModuleObject,
756 : MaterialNames(1),
757 : minLamValue));
758 0 : ShowContinueError(state,
759 0 : format("{} requires the minumum value = 0.1 micron in the entered table name={}",
760 0 : ipsc->cAlphaFieldNames(5),
761 : MaterialNames(5)));
762 : }
763 1 : if (maxLamValue > 4.0) {
764 0 : ErrorsFound = true;
765 0 : ShowSevereError(state,
766 0 : format("{}=\"{}\", Invalid maximum value of wavelength = {:.2R}.",
767 0 : state.dataHeatBalMgr->CurrentModuleObject,
768 : MaterialNames(1),
769 : maxLamValue));
770 0 : ShowContinueError(state,
771 0 : format("{} requires the maximum value = 4.0 microns in the entered table name={}",
772 0 : ipsc->cAlphaFieldNames(5),
773 : MaterialNames(5)));
774 : }
775 : }
776 : }
777 1 : if (ipsc->lAlphaFieldBlanks(6)) {
778 0 : ErrorsFound = true;
779 0 : ShowSevereError(state, format("{}=\"{}\", blank field.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
780 0 : ShowContinueError(state, " Table name must be entered when the key SpectralAndAngle is selected as Optical Data Type.");
781 : } else {
782 1 : thisMaterial->GlassSpecAngFRefleDataPtr = Curve::GetCurveIndex(state, MaterialNames(6));
783 1 : if (thisMaterial->GlassSpecAngFRefleDataPtr == 0) {
784 0 : ErrorsFound = true;
785 0 : ShowSevereError(state, format("{}=\"{}\", Invalid name.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
786 0 : ShowContinueError(state,
787 0 : format("{} requires a valid table object name, entered input={}", ipsc->cAlphaFieldNames(6), MaterialNames(6)));
788 : } else {
789 2 : ErrorsFound |= Curve::CheckCurveDims(state,
790 : thisMaterial->GlassSpecAngFRefleDataPtr, // Curve index
791 : {2}, // Valid dimensions
792 : RoutineName, // Routine name
793 1 : state.dataHeatBalMgr->CurrentModuleObject, // Object Type
794 : thisMaterial->Name, // Object Name
795 1 : ipsc->cAlphaFieldNames(6)); // Field Name
796 :
797 1 : GetCurveMinMaxValues(state, thisMaterial->GlassSpecAngFRefleDataPtr, minAngValue, maxAngValue, minLamValue, maxLamValue);
798 1 : if (minAngValue > 1.0e-6) {
799 0 : ErrorsFound = true;
800 0 : ShowSevereError(state,
801 0 : format("{}=\"{}\", Invalid minimum value of angle = {:.2R}.",
802 0 : state.dataHeatBalMgr->CurrentModuleObject,
803 : MaterialNames(1),
804 : minAngValue));
805 0 : ShowContinueError(
806 : state,
807 0 : format("{} requires the minumum value = 0.0 in the entered table name={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
808 : }
809 1 : if (std::abs(maxAngValue - 90.0) > 1.0e-6) {
810 0 : ErrorsFound = true;
811 0 : ShowSevereError(state,
812 0 : format("{}=\"{}\", Invalid maximum value of angle = {:.2R}.",
813 0 : state.dataHeatBalMgr->CurrentModuleObject,
814 : MaterialNames(1),
815 : maxAngValue));
816 0 : ShowContinueError(
817 : state,
818 0 : format("{} requires the maximum value = 90.0 in the entered table name={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
819 : }
820 1 : if (minLamValue < 0.1) {
821 0 : ErrorsFound = true;
822 0 : ShowSevereError(state,
823 0 : format("{}=\"{}\", Invalid minimum value of wavelength = {:.2R}.",
824 0 : state.dataHeatBalMgr->CurrentModuleObject,
825 : MaterialNames(1),
826 : minLamValue));
827 0 : ShowContinueError(state,
828 0 : format("{} requires the minumum value = 0.1 micron in the entered table name={}",
829 0 : ipsc->cAlphaFieldNames(5),
830 : MaterialNames(5)));
831 : }
832 1 : if (maxLamValue > 4.0) {
833 0 : ErrorsFound = true;
834 0 : ShowSevereError(state,
835 0 : format("{}=\"{}\", Invalid maximum value of wavelength = {:.2R}.",
836 0 : state.dataHeatBalMgr->CurrentModuleObject,
837 : MaterialNames(1),
838 : maxLamValue));
839 0 : ShowContinueError(state,
840 0 : format("{} requires the maximum value = 4.0 microns in the entered table name={}",
841 0 : ipsc->cAlphaFieldNames(5),
842 : MaterialNames(5)));
843 : }
844 : }
845 : }
846 1 : if (ipsc->lAlphaFieldBlanks(7)) {
847 0 : ErrorsFound = true;
848 0 : ShowSevereError(state, format("{}=\"{}\", blank field.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
849 0 : ShowContinueError(state, " Table name must be entered when the key SpectralAndAngle is selected as Optical Data Type.");
850 : } else {
851 1 : thisMaterial->GlassSpecAngBRefleDataPtr = Curve::GetCurveIndex(state, MaterialNames(7));
852 1 : if (thisMaterial->GlassSpecAngBRefleDataPtr == 0) {
853 0 : ErrorsFound = true;
854 0 : ShowSevereError(state, format("{}=\"{}\", Invalid name.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
855 0 : ShowContinueError(state,
856 0 : format("{} requires a valid table object name, entered input={}", ipsc->cAlphaFieldNames(7), MaterialNames(7)));
857 : } else {
858 2 : ErrorsFound |= Curve::CheckCurveDims(state,
859 : thisMaterial->GlassSpecAngBRefleDataPtr, // Curve index
860 : {2}, // Valid dimensions
861 : RoutineName, // Routine name
862 1 : state.dataHeatBalMgr->CurrentModuleObject, // Object Type
863 : thisMaterial->Name, // Object Name
864 1 : ipsc->cAlphaFieldNames(7)); // Field Name
865 :
866 1 : GetCurveMinMaxValues(state, thisMaterial->GlassSpecAngBRefleDataPtr, minAngValue, maxAngValue, minLamValue, maxLamValue);
867 1 : if (minAngValue > 1.0e-6) {
868 0 : ErrorsFound = true;
869 0 : ShowSevereError(state,
870 0 : format("{}=\"{}\", Invalid minimum value of angle = {:.2R}.",
871 0 : state.dataHeatBalMgr->CurrentModuleObject,
872 : MaterialNames(1),
873 : minAngValue));
874 0 : ShowContinueError(
875 : state,
876 0 : format("{} requires the minumum value = 0.0 in the entered table name={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
877 : }
878 1 : if (std::abs(maxAngValue - 90.0) > 1.0e-6) {
879 0 : ErrorsFound = true;
880 0 : ShowSevereError(state,
881 0 : format("{}=\"{}\", Invalid maximum value of angle = {:.2R}.",
882 0 : state.dataHeatBalMgr->CurrentModuleObject,
883 : MaterialNames(1),
884 : maxAngValue));
885 0 : ShowContinueError(
886 : state,
887 0 : format("{} requires the maximum value = 90.0 in the entered table name={}", ipsc->cAlphaFieldNames(5), MaterialNames(5)));
888 : }
889 1 : if (minLamValue < 0.1) {
890 0 : ErrorsFound = true;
891 0 : ShowSevereError(state,
892 0 : format("{}=\"{}\", Invalid minimum value of wavelength = {:.2R}.",
893 0 : state.dataHeatBalMgr->CurrentModuleObject,
894 : MaterialNames(1),
895 : minLamValue));
896 0 : ShowContinueError(state,
897 0 : format("{} requires the minumum value = 0.1 micron in the entered table name={}",
898 0 : ipsc->cAlphaFieldNames(5),
899 : MaterialNames(5)));
900 : }
901 1 : if (maxLamValue > 4.0) {
902 0 : ErrorsFound = true;
903 0 : ShowSevereError(state,
904 0 : format("{}=\"{}\", Invalid maximum value of wavelength = {:.2R}.",
905 0 : state.dataHeatBalMgr->CurrentModuleObject,
906 : MaterialNames(1),
907 : maxLamValue));
908 0 : ShowContinueError(state,
909 0 : format("{} requires the maximum value = 4.0 microns in the entered table name={}",
910 0 : ipsc->cAlphaFieldNames(5),
911 : MaterialNames(5)));
912 : }
913 : }
914 : }
915 : }
916 : }
917 :
918 : // Glass materials, alternative input: index of refraction and extinction coefficient
919 :
920 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Glazing:RefractionExtinctionMethod";
921 806 : for (Loop = 1; Loop <= state.dataHeatBal->W5GlsMatAlt; ++Loop) {
922 :
923 : // Call Input Get routine to retrieve material data
924 30 : ip->getObjectItem(state,
925 10 : state.dataHeatBalMgr->CurrentModuleObject,
926 : Loop,
927 : MaterialNames,
928 : MaterialNumAlpha,
929 : MaterialProps,
930 : MaterialNumProp,
931 : IOStat,
932 10 : ipsc->lNumericFieldBlanks,
933 10 : ipsc->lAlphaFieldBlanks,
934 10 : ipsc->cAlphaFieldNames,
935 10 : ipsc->cNumericFieldNames);
936 20 : if (GlobalNames::VerifyUniqueInterObjectName(state,
937 10 : state.dataHeatBalMgr->UniqueMaterialNames,
938 10 : MaterialNames(1),
939 10 : state.dataHeatBalMgr->CurrentModuleObject,
940 10 : ipsc->cAlphaFieldNames(1),
941 : ErrorsFound)) {
942 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
943 0 : continue;
944 : }
945 :
946 10 : ++MaterNum;
947 10 : auto *thisMaterial = new MaterialChild;
948 10 : state.dataMaterial->Material(MaterNum) = thisMaterial;
949 10 : thisMaterial->group = Group::WindowGlass;
950 :
951 : // Load the material derived type from the input data.
952 :
953 10 : thisMaterial->Name = MaterialNames(1);
954 10 : thisMaterial->Roughness = SurfaceRoughness::VerySmooth;
955 10 : thisMaterial->Thickness = MaterialProps(1);
956 10 : thisMaterial->ROnly = true;
957 :
958 : // Calculate solar and visible transmittance and reflectance at normal incidence from thickness,
959 : // index of refraction and extinction coefficient. With the alternative input the front and back
960 : // properties are assumed to be the same.
961 :
962 10 : ReflectivitySol = pow_2((MaterialProps(2) - 1.0) / (MaterialProps(2) + 1.0));
963 10 : ReflectivityVis = pow_2((MaterialProps(4) - 1.0) / (MaterialProps(4) + 1.0));
964 10 : TransmittivitySol = std::exp(-MaterialProps(3) * MaterialProps(1));
965 10 : TransmittivityVis = std::exp(-MaterialProps(5) * MaterialProps(1));
966 10 : thisMaterial->Trans = TransmittivitySol * pow_2(1.0 - ReflectivitySol) / (1.0 - pow_2(ReflectivitySol * TransmittivitySol));
967 10 : thisMaterial->ReflectSolBeamFront =
968 10 : ReflectivitySol * (1.0 + pow_2(1.0 - ReflectivitySol) * pow_2(TransmittivitySol) / (1.0 - pow_2(ReflectivitySol * TransmittivitySol)));
969 10 : thisMaterial->ReflectSolBeamBack = thisMaterial->ReflectSolBeamFront;
970 10 : thisMaterial->TransVis = TransmittivityVis * pow_2(1.0 - ReflectivityVis) / (1.0 - pow_2(ReflectivityVis * TransmittivityVis));
971 :
972 10 : thisMaterial->ReflectVisBeamFront =
973 10 : ReflectivityVis * (1.0 + pow_2(1.0 - ReflectivityVis) * pow_2(TransmittivityVis) / (1.0 - pow_2(ReflectivityVis * TransmittivityVis)));
974 10 : thisMaterial->ReflectVisBeamBack = thisMaterial->ReflectSolBeamFront;
975 10 : thisMaterial->TransThermal = MaterialProps(6);
976 10 : thisMaterial->AbsorpThermalFront = MaterialProps(7);
977 10 : thisMaterial->AbsorpThermalBack = MaterialProps(7);
978 10 : thisMaterial->Conductivity = MaterialProps(8);
979 10 : thisMaterial->GlassTransDirtFactor = MaterialProps(9);
980 10 : if (MaterialProps(9) == 0.0) thisMaterial->GlassTransDirtFactor = 1.0;
981 10 : thisMaterial->AbsorpThermal = thisMaterial->AbsorpThermalBack;
982 :
983 10 : if (thisMaterial->Conductivity > 0.0) {
984 10 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Thickness / thisMaterial->Conductivity;
985 10 : thisMaterial->Resistance = state.dataHeatBal->NominalR(MaterNum);
986 : }
987 :
988 10 : thisMaterial->GlassSpectralDataPtr = 0;
989 :
990 10 : if (MaterialProps(6) + MaterialProps(7) >= 1.0) {
991 0 : ErrorsFound = true;
992 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
993 0 : ShowContinueError(state, format("{} + {} not < 1.0", ipsc->cNumericFieldNames(6), ipsc->cNumericFieldNames(7)));
994 : }
995 :
996 10 : if (MaterialNames(2) == "") {
997 0 : thisMaterial->SolarDiffusing = false;
998 10 : } else if (MaterialNames(2) == "YES") {
999 0 : thisMaterial->SolarDiffusing = true;
1000 10 : } else if (MaterialNames(2) == "NO") {
1001 10 : thisMaterial->SolarDiffusing = false;
1002 : } else {
1003 0 : ErrorsFound = true;
1004 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
1005 0 : ShowContinueError(state, format("{} must be Yes or No, entered value={}", ipsc->cNumericFieldNames(2), MaterialNames(4)));
1006 : }
1007 : }
1008 :
1009 : // Glass materials, equivalent layer (ASHWAT) method
1010 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Glazing:EquivalentLayer";
1011 800 : for (Loop = 1; Loop <= state.dataHeatBal->W5GlsMatEQL; ++Loop) {
1012 :
1013 : // Call Input Get routine to retrieve material data
1014 12 : ip->getObjectItem(state,
1015 4 : state.dataHeatBalMgr->CurrentModuleObject,
1016 : Loop,
1017 : MaterialNames,
1018 : MaterialNumAlpha,
1019 : MaterialProps,
1020 : MaterialNumProp,
1021 : IOStat,
1022 4 : ipsc->lNumericFieldBlanks,
1023 4 : ipsc->lAlphaFieldBlanks,
1024 4 : ipsc->cAlphaFieldNames,
1025 4 : ipsc->cNumericFieldNames);
1026 8 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1027 4 : state.dataHeatBalMgr->UniqueMaterialNames,
1028 4 : MaterialNames(1),
1029 4 : state.dataHeatBalMgr->CurrentModuleObject,
1030 4 : ipsc->cAlphaFieldNames(1),
1031 : ErrorsFound)) {
1032 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1033 0 : continue;
1034 : }
1035 :
1036 4 : ++MaterNum;
1037 4 : auto *thisMaterial = new MaterialChild;
1038 4 : state.dataMaterial->Material(MaterNum) = thisMaterial;
1039 4 : thisMaterial->group = Group::GlassEquivalentLayer;
1040 :
1041 : // Load the material derived type from the input data.
1042 4 : thisMaterial->Name = MaterialNames(1);
1043 4 : thisMaterial->Roughness = SurfaceRoughness::VerySmooth;
1044 4 : thisMaterial->ROnly = true;
1045 :
1046 4 : thisMaterial->TausFrontBeamBeam = MaterialProps(1);
1047 4 : thisMaterial->TausBackBeamBeam = MaterialProps(2);
1048 4 : thisMaterial->ReflFrontBeamBeam = MaterialProps(3);
1049 4 : thisMaterial->ReflBackBeamBeam = MaterialProps(4);
1050 4 : thisMaterial->TausFrontBeamBeamVis = MaterialProps(5);
1051 4 : thisMaterial->TausBackBeamBeamVis = MaterialProps(6);
1052 4 : thisMaterial->ReflFrontBeamBeamVis = MaterialProps(7);
1053 4 : thisMaterial->ReflBackBeamBeamVis = MaterialProps(8);
1054 4 : thisMaterial->TausFrontBeamDiff = MaterialProps(9);
1055 4 : thisMaterial->TausBackBeamDiff = MaterialProps(10);
1056 4 : thisMaterial->ReflFrontBeamDiff = MaterialProps(11);
1057 4 : thisMaterial->ReflBackBeamDiff = MaterialProps(12);
1058 4 : thisMaterial->TausFrontBeamDiffVis = MaterialProps(13);
1059 4 : thisMaterial->TausBackBeamDiffVis = MaterialProps(14);
1060 4 : thisMaterial->ReflFrontBeamDiffVis = MaterialProps(15);
1061 4 : thisMaterial->ReflBackBeamDiffVis = MaterialProps(16);
1062 4 : thisMaterial->TausDiffDiff = MaterialProps(17);
1063 4 : thisMaterial->ReflFrontDiffDiff = MaterialProps(18);
1064 4 : thisMaterial->ReflBackDiffDiff = MaterialProps(19);
1065 4 : thisMaterial->TausDiffDiffVis = MaterialProps(20);
1066 4 : thisMaterial->ReflFrontDiffDiffVis = MaterialProps(21);
1067 4 : thisMaterial->ReflBackDiffDiffVis = MaterialProps(22);
1068 4 : thisMaterial->TausThermal = MaterialProps(23);
1069 4 : thisMaterial->EmissThermalFront = MaterialProps(24);
1070 4 : thisMaterial->EmissThermalBack = MaterialProps(25);
1071 4 : thisMaterial->Resistance = MaterialProps(26);
1072 4 : if (thisMaterial->Resistance <= 0.0) thisMaterial->Resistance = 0.158; // equivalent to single pane of 1/4" inch standard glass
1073 : // Assumes thermal emissivity is the same as thermal absorptance
1074 4 : thisMaterial->AbsorpThermalFront = thisMaterial->EmissThermalFront;
1075 4 : thisMaterial->AbsorpThermalBack = thisMaterial->EmissThermalBack;
1076 4 : thisMaterial->TransThermal = thisMaterial->TausThermal;
1077 :
1078 4 : if (Util::SameString(MaterialNames(2), "SpectralAverage")) thisMaterial->GlassSpectralDataPtr = 0;
1079 :
1080 : // IF(dataMaterial.Material(MaterNum)%GlassSpectralDataPtr == 0 .AND. Util::SameString(MaterialNames(2),'Spectral')) THEN
1081 : // ErrorsFound = .TRUE.
1082 : // CALL ShowSevereError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//'="'//Trim(dataMaterial.Material(MaterNum)%Name)// &
1083 : // '" has '//TRIM(cAlphaFieldNames(2))//' = Spectral but has no matching MaterialProperty:GlazingSpectralData set')
1084 : // if (ipsc->lAlphaFieldBlanks(3)) THEN
1085 : // CALL ShowContinueError(state, '...'//TRIM(cAlphaFieldNames(3))//' is blank.')
1086 : // ELSE
1087 : // CALL ShowContinueError(state, '...'//TRIM(cAlphaFieldNames(3))//'="'//TRIM(MaterialNames(3))// &
1088 : // '" not found as item in MaterialProperty:GlazingSpectralData objects.')
1089 : // END IF
1090 : // END IF
1091 :
1092 4 : if (!Util::SameString(MaterialNames(2), "SpectralAverage")) {
1093 0 : ErrorsFound = true;
1094 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + thisMaterial->Name + "\", invalid specification.");
1095 0 : ShowContinueError(state, ipsc->cAlphaFieldNames(2) + " must be SpectralAverage, value=" + MaterialNames(2));
1096 : }
1097 :
1098 : } // W5GlsMatEQL loop
1099 :
1100 : // Window gas materials (for gaps with a single gas)
1101 :
1102 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Gas";
1103 1609 : for (Loop = 1; Loop <= state.dataHeatBal->W5GasMat; ++Loop) {
1104 :
1105 : // Call Input Get routine to retrieve material data
1106 2439 : ip->getObjectItem(state,
1107 813 : state.dataHeatBalMgr->CurrentModuleObject,
1108 : Loop,
1109 : MaterialNames,
1110 : MaterialNumAlpha,
1111 : MaterialProps,
1112 : MaterialNumProp,
1113 : IOStat,
1114 813 : ipsc->lNumericFieldBlanks,
1115 813 : ipsc->lAlphaFieldBlanks,
1116 813 : ipsc->cAlphaFieldNames,
1117 813 : ipsc->cNumericFieldNames);
1118 1626 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1119 813 : state.dataHeatBalMgr->UniqueMaterialNames,
1120 813 : MaterialNames(1),
1121 813 : state.dataHeatBalMgr->CurrentModuleObject,
1122 813 : ipsc->cAlphaFieldNames(1),
1123 : ErrorsFound)) {
1124 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1125 0 : continue;
1126 : }
1127 :
1128 813 : ++MaterNum;
1129 813 : auto *matGas = new MaterialGasMix;
1130 813 : state.dataMaterial->Material(MaterNum) = matGas;
1131 813 : matGas->group = Group::WindowGas;
1132 813 : matGas->numGases = 1;
1133 813 : matGas->gasFracts[0] = 1.0;
1134 :
1135 : // Load the material derived type from the input data.
1136 :
1137 813 : matGas->Name = MaterialNames(1);
1138 813 : matGas->gases[0].type = static_cast<GasType>(getEnumValue(gasTypeNamesUC, Util::makeUPPER(MaterialNames(2))));
1139 813 : matGas->Roughness = SurfaceRoughness::MediumRough;
1140 :
1141 813 : matGas->Thickness = MaterialProps(1);
1142 813 : matGas->ROnly = true;
1143 :
1144 813 : gasType = matGas->gases[0].type;
1145 813 : if (gasType != GasType::Custom) {
1146 811 : matGas->gases[0] = gases[(int)gasType];
1147 : }
1148 :
1149 : // Custom gas
1150 :
1151 813 : if (gasType == GasType::Custom) {
1152 2 : matGas->gases[0].con.c0 = MaterialProps(2);
1153 2 : matGas->gases[0].con.c1 = MaterialProps(3);
1154 2 : matGas->gases[0].con.c2 = MaterialProps(4);
1155 2 : matGas->gases[0].vis.c0 = MaterialProps(5);
1156 2 : matGas->gases[0].vis.c1 = MaterialProps(6);
1157 2 : matGas->gases[0].vis.c2 = MaterialProps(7);
1158 2 : matGas->gases[0].cp.c0 = MaterialProps(8);
1159 2 : matGas->gases[0].cp.c1 = MaterialProps(9);
1160 2 : matGas->gases[0].cp.c2 = MaterialProps(10);
1161 2 : matGas->gases[0].wght = MaterialProps(11);
1162 2 : matGas->gases[0].specHeatRatio = MaterialProps(12);
1163 :
1164 : // Check for errors in custom gas properties
1165 : // IF(dataMaterial.Material(MaterNum)%GasCon(1,1) <= 0.0) THEN
1166 : // ErrorsFound = .TRUE.
1167 : // CALL ShowSevereError(state, 'Conductivity Coefficient A for custom window gas='&
1168 : // //TRIM(MaterialNames(1))//' should be > 0.')
1169 : // END IF
1170 :
1171 2 : if (matGas->gases[0].vis.c0 <= 0.0) {
1172 0 : ErrorsFound = true;
1173 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1174 0 : ShowContinueError(state, ipsc->cNumericFieldNames(5) + " not > 0.0");
1175 : }
1176 2 : if (matGas->gases[0].cp.c0 <= 0.0) {
1177 0 : ErrorsFound = true;
1178 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1179 0 : ShowContinueError(state, ipsc->cNumericFieldNames(8) + " not > 0.0");
1180 : }
1181 2 : if (matGas->gases[0].wght <= 0.0) {
1182 0 : ErrorsFound = true;
1183 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1184 0 : ShowContinueError(state, ipsc->cNumericFieldNames(11) + " not > 0.0");
1185 : }
1186 : }
1187 :
1188 : // Nominal resistance of gap at room temperature
1189 813 : if (!ErrorsFound) {
1190 813 : DenomRGas = (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
1191 813 : if (DenomRGas > 0.0) {
1192 813 : state.dataHeatBal->NominalR(MaterNum) = matGas->Thickness / DenomRGas;
1193 : } else {
1194 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1195 0 : ShowContinueError(state,
1196 0 : format("Nominal resistance of gap at room temperature calculated at a negative Conductivity=[{:.3R}].", DenomRGas));
1197 0 : ErrorsFound = true;
1198 : }
1199 : }
1200 : }
1201 :
1202 : // Window gap materials (for gaps with a single gas for EquivalentLayer)
1203 :
1204 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Gap:EquivalentLayer";
1205 804 : for (Loop = 1; Loop <= state.dataHeatBal->W5GapMatEQL; ++Loop) {
1206 :
1207 : // Call Input Get routine to retrieve material data
1208 24 : ip->getObjectItem(state,
1209 8 : state.dataHeatBalMgr->CurrentModuleObject,
1210 : Loop,
1211 : MaterialNames,
1212 : MaterialNumAlpha,
1213 : MaterialProps,
1214 : MaterialNumProp,
1215 : IOStat,
1216 8 : ipsc->lNumericFieldBlanks,
1217 8 : ipsc->lAlphaFieldBlanks,
1218 8 : ipsc->cAlphaFieldNames,
1219 8 : ipsc->cNumericFieldNames);
1220 16 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1221 8 : state.dataHeatBalMgr->UniqueMaterialNames,
1222 8 : MaterialNames(1),
1223 8 : state.dataHeatBalMgr->CurrentModuleObject,
1224 8 : ipsc->cAlphaFieldNames(1),
1225 : ErrorsFound)) {
1226 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1227 0 : continue;
1228 : }
1229 :
1230 8 : ++MaterNum;
1231 8 : auto *matGas = new MaterialGasMix;
1232 8 : state.dataMaterial->Material(MaterNum) = matGas;
1233 8 : matGas->group = Group::GapEquivalentLayer;
1234 8 : matGas->numGases = 1;
1235 8 : matGas->gasFracts[0] = 1.0;
1236 :
1237 : // Load the material derived type from the input data.
1238 :
1239 8 : matGas->Name = MaterialNames(1);
1240 8 : matGas->gases[0].type = static_cast<GasType>(getEnumValue(gasTypeNamesUC, Util::makeUPPER(MaterialNames(2)))); // Error check?
1241 :
1242 8 : matGas->Roughness = SurfaceRoughness::MediumRough;
1243 :
1244 8 : matGas->Thickness = MaterialProps(1);
1245 8 : matGas->ROnly = true;
1246 :
1247 8 : gasType = matGas->gases[0].type;
1248 8 : if (gasType != GasType::Custom) {
1249 8 : matGas->gases[0] = gases[(int)gasType];
1250 : }
1251 :
1252 8 : if (!ipsc->lAlphaFieldBlanks(2)) {
1253 : // Get gap vent type
1254 8 : matGas->gapVentType = static_cast<GapVentType>(getEnumValue(gapVentTypeNamesUC, Util::makeUPPER(MaterialNames(3))));
1255 : }
1256 :
1257 8 : if (gasType == GasType::Custom) {
1258 0 : for (ICoeff = 1; ICoeff <= 3; ++ICoeff) {
1259 0 : matGas->gases[0].con.c0 = MaterialProps(2);
1260 0 : matGas->gases[0].con.c1 = MaterialProps(3);
1261 0 : matGas->gases[0].con.c2 = MaterialProps(4);
1262 0 : matGas->gases[0].vis.c0 = MaterialProps(5);
1263 0 : matGas->gases[0].vis.c1 = MaterialProps(6);
1264 0 : matGas->gases[0].vis.c2 = MaterialProps(7);
1265 0 : matGas->gases[0].cp.c0 = MaterialProps(8);
1266 0 : matGas->gases[0].cp.c1 = MaterialProps(9);
1267 0 : matGas->gases[0].cp.c2 = MaterialProps(10);
1268 : }
1269 0 : matGas->gases[0].wght = MaterialProps(11);
1270 0 : matGas->gases[0].specHeatRatio = MaterialProps(12);
1271 :
1272 0 : if (matGas->gases[0].vis.c0 <= 0.0) {
1273 0 : ErrorsFound = true;
1274 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
1275 0 : ShowContinueError(state, format("{} not > 0.0", ipsc->cNumericFieldNames(5)));
1276 : }
1277 0 : if (matGas->gases[0].cp.c0 <= 0.0) {
1278 0 : ErrorsFound = true;
1279 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
1280 0 : ShowContinueError(state, format("{} not > 0.0", ipsc->cNumericFieldNames(8)));
1281 : }
1282 0 : if (matGas->gases[0].wght <= 0.0) {
1283 0 : ErrorsFound = true;
1284 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
1285 0 : ShowContinueError(state, format("{} not > 0.0", ipsc->cNumericFieldNames(11)));
1286 : }
1287 : }
1288 :
1289 : // Nominal resistance of gap at room temperature
1290 8 : if (!ErrorsFound) {
1291 8 : DenomRGas = (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
1292 8 : if (DenomRGas > 0.0) {
1293 8 : state.dataHeatBal->NominalR(MaterNum) = matGas->Thickness / DenomRGas;
1294 : } else {
1295 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
1296 0 : ShowContinueError(state,
1297 0 : format("Nominal resistance of gap at room temperature calculated at a negative Conductivity=[{:.3R}].", DenomRGas));
1298 0 : ErrorsFound = true;
1299 : }
1300 : }
1301 : } // for (Loop : W5MatEQL)
1302 :
1303 : // Window gas mixtures (for gaps with two or more gases)
1304 :
1305 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:GasMixture";
1306 812 : for (Loop = 1; Loop <= state.dataHeatBal->W5GasMatMixture; ++Loop) {
1307 :
1308 : // Call Input Get routine to retrieve material data
1309 32 : ip->getObjectItem(state,
1310 16 : state.dataHeatBalMgr->CurrentModuleObject,
1311 : Loop,
1312 16 : ipsc->cAlphaArgs,
1313 : MaterialNumAlpha,
1314 : MaterialProps,
1315 : MaterialNumProp,
1316 : IOStat,
1317 16 : ipsc->lNumericFieldBlanks,
1318 16 : ipsc->lAlphaFieldBlanks,
1319 16 : ipsc->cAlphaFieldNames,
1320 16 : ipsc->cNumericFieldNames);
1321 32 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1322 16 : state.dataHeatBalMgr->UniqueMaterialNames,
1323 16 : ipsc->cAlphaArgs(1),
1324 16 : state.dataHeatBalMgr->CurrentModuleObject,
1325 16 : ipsc->cAlphaFieldNames(1),
1326 : ErrorsFound)) {
1327 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1328 0 : continue;
1329 : }
1330 :
1331 16 : ++MaterNum;
1332 16 : auto *matGas = new MaterialGasMix;
1333 16 : state.dataMaterial->Material(MaterNum) = matGas;
1334 16 : matGas->group = Group::WindowGasMixture;
1335 16 : matGas->gases[0].type = matGas->gases[1].type = matGas->gases[2].type = matGas->gases[3].type = matGas->gases[4].type = GasType::Invalid;
1336 :
1337 : // Load the material derived type from the input data.
1338 :
1339 16 : matGas->Name = ipsc->cAlphaArgs(1);
1340 16 : NumGases = MaterialProps(2);
1341 16 : matGas->numGases = NumGases;
1342 48 : for (NumGas = 0; NumGas < NumGases; ++NumGas) {
1343 32 : auto &gas = matGas->gases[NumGas];
1344 32 : gas.type = static_cast<GasType>(getEnumValue(gasTypeNamesUC, Util::makeUPPER(ipsc->cAlphaArgs(2 + NumGas))));
1345 32 : if (gas.type == GasType::Invalid) {
1346 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, ipsc->cAlphaArgs(1 + NumGas)));
1347 : // Error check?
1348 0 : ErrorsFound = true;
1349 : }
1350 : }
1351 :
1352 16 : matGas->Roughness = SurfaceRoughness::MediumRough; // Unused
1353 :
1354 16 : matGas->Thickness = MaterialProps(1);
1355 16 : if (matGas->Thickness <= 0.0) {
1356 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, ipsc->cAlphaArgs(1)));
1357 0 : ShowContinueError(state, ipsc->cNumericFieldNames(1) + " must be greater than 0.");
1358 : }
1359 16 : matGas->ROnly = true;
1360 :
1361 48 : for (NumGas = 0; NumGas < NumGases; ++NumGas) {
1362 32 : GasType gasType = matGas->gases[NumGas].type;
1363 32 : if (gasType != GasType::Custom) {
1364 32 : matGas->gasFracts[NumGas] = MaterialProps(3 + NumGas);
1365 32 : matGas->gases[NumGas] = gases[(int)gasType];
1366 : }
1367 : }
1368 :
1369 : // Nominal resistance of gap at room temperature (based on first gas in mixture)
1370 16 : state.dataHeatBal->NominalR(MaterNum) =
1371 16 : matGas->Thickness / (matGas->gases[0].con.c0 + matGas->gases[0].con.c1 * 300.0 + matGas->gases[0].con.c2 * 90000.0);
1372 : }
1373 :
1374 : // Window Shade Materials
1375 :
1376 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Shade";
1377 813 : for (Loop = 1; Loop <= state.dataHeatBal->TotShades; ++Loop) {
1378 :
1379 : // Call Input Get routine to retrieve material data
1380 51 : ip->getObjectItem(state,
1381 17 : state.dataHeatBalMgr->CurrentModuleObject,
1382 : Loop,
1383 : MaterialNames,
1384 : MaterialNumAlpha,
1385 : MaterialProps,
1386 : MaterialNumProp,
1387 : IOStat,
1388 17 : ipsc->lNumericFieldBlanks,
1389 17 : ipsc->lAlphaFieldBlanks,
1390 17 : ipsc->cAlphaFieldNames,
1391 17 : ipsc->cNumericFieldNames);
1392 34 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1393 17 : state.dataHeatBalMgr->UniqueMaterialNames,
1394 17 : MaterialNames(1),
1395 17 : state.dataHeatBalMgr->CurrentModuleObject,
1396 17 : ipsc->cAlphaFieldNames(1),
1397 : ErrorsFound)) {
1398 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1399 0 : continue;
1400 : }
1401 :
1402 17 : ++MaterNum;
1403 17 : auto *thisMaterial = new MaterialChild;
1404 17 : state.dataMaterial->Material(MaterNum) = thisMaterial;
1405 17 : thisMaterial->group = Group::Shade;
1406 :
1407 : // Load the material derived type from the input data.
1408 :
1409 17 : thisMaterial->Name = MaterialNames(1);
1410 17 : thisMaterial->Roughness = SurfaceRoughness::MediumRough;
1411 17 : thisMaterial->Trans = MaterialProps(1);
1412 17 : thisMaterial->ReflectShade = MaterialProps(2);
1413 17 : thisMaterial->TransVis = MaterialProps(3);
1414 17 : thisMaterial->ReflectShadeVis = MaterialProps(4);
1415 17 : thisMaterial->AbsorpThermal = MaterialProps(5);
1416 17 : thisMaterial->AbsorpThermalInput = MaterialProps(5);
1417 17 : thisMaterial->TransThermal = MaterialProps(6);
1418 17 : thisMaterial->Thickness = MaterialProps(7);
1419 17 : thisMaterial->Conductivity = MaterialProps(8);
1420 17 : thisMaterial->AbsorpSolar = max(0.0, 1.0 - thisMaterial->Trans - thisMaterial->ReflectShade);
1421 17 : thisMaterial->AbsorpSolarInput = thisMaterial->AbsorpSolar;
1422 17 : thisMaterial->WinShadeToGlassDist = MaterialProps(9);
1423 17 : thisMaterial->WinShadeTopOpeningMult = MaterialProps(10);
1424 17 : thisMaterial->WinShadeBottomOpeningMult = MaterialProps(11);
1425 17 : thisMaterial->WinShadeLeftOpeningMult = MaterialProps(12);
1426 17 : thisMaterial->WinShadeRightOpeningMult = MaterialProps(13);
1427 17 : thisMaterial->WinShadeAirFlowPermeability = MaterialProps(14);
1428 17 : thisMaterial->ROnly = true;
1429 :
1430 17 : if (thisMaterial->Conductivity > 0.0) {
1431 17 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Thickness / thisMaterial->Conductivity;
1432 : } else {
1433 0 : state.dataHeatBal->NominalR(MaterNum) = 1.0;
1434 : }
1435 :
1436 17 : if (MaterialProps(1) + MaterialProps(2) >= 1.0) {
1437 0 : ErrorsFound = true;
1438 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1439 0 : ShowContinueError(state, ipsc->cNumericFieldNames(1) + " + " + ipsc->cNumericFieldNames(2) + " not < 1.0");
1440 : }
1441 :
1442 17 : if (MaterialProps(3) + MaterialProps(4) >= 1.0) {
1443 0 : ErrorsFound = true;
1444 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1445 0 : ShowContinueError(state, ipsc->cNumericFieldNames(3) + " + " + ipsc->cNumericFieldNames(4) + " not < 1.0");
1446 : }
1447 :
1448 17 : if (MaterialProps(5) + MaterialProps(6) >= 1.0) {
1449 0 : ErrorsFound = true;
1450 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1451 0 : ShowContinueError(state, ipsc->cNumericFieldNames(5) + " + " + ipsc->cNumericFieldNames(6) + " not < 1.0");
1452 : }
1453 : }
1454 :
1455 : // Window Shade Materials
1456 :
1457 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Shade:EquivalentLayer";
1458 798 : for (Loop = 1; Loop <= state.dataHeatBal->TotShadesEQL; ++Loop) {
1459 :
1460 2 : MaterialProps = 0;
1461 :
1462 : // Call Input Get routine to retrieve material data
1463 6 : ip->getObjectItem(state,
1464 2 : state.dataHeatBalMgr->CurrentModuleObject,
1465 : Loop,
1466 : MaterialNames,
1467 : MaterialNumAlpha,
1468 : MaterialProps,
1469 : MaterialNumProp,
1470 : IOStat,
1471 2 : ipsc->lNumericFieldBlanks,
1472 2 : ipsc->lAlphaFieldBlanks,
1473 2 : ipsc->cAlphaFieldNames,
1474 2 : ipsc->cNumericFieldNames);
1475 4 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1476 2 : state.dataHeatBalMgr->UniqueMaterialNames,
1477 2 : MaterialNames(1),
1478 2 : state.dataHeatBalMgr->CurrentModuleObject,
1479 2 : ipsc->cAlphaFieldNames(1),
1480 : ErrorsFound)) {
1481 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1482 0 : continue;
1483 : }
1484 :
1485 2 : ++MaterNum;
1486 2 : auto *thisMaterial = new MaterialChild;
1487 2 : state.dataMaterial->Material(MaterNum) = thisMaterial;
1488 2 : thisMaterial->group = Group::ShadeEquivalentLayer;
1489 :
1490 2 : thisMaterial->Name = MaterialNames(1);
1491 2 : thisMaterial->Roughness = SurfaceRoughness::MediumRough;
1492 2 : thisMaterial->ROnly = true;
1493 :
1494 : // Front side and back side have the same beam-Beam Transmittance
1495 2 : thisMaterial->TausFrontBeamBeam = MaterialProps(1);
1496 2 : thisMaterial->TausBackBeamBeam = MaterialProps(1);
1497 2 : thisMaterial->TausFrontBeamDiff = MaterialProps(2);
1498 2 : thisMaterial->TausBackBeamDiff = MaterialProps(3);
1499 2 : thisMaterial->ReflFrontBeamDiff = MaterialProps(4);
1500 2 : thisMaterial->ReflBackBeamDiff = MaterialProps(5);
1501 2 : thisMaterial->TausFrontBeamBeamVis = MaterialProps(6);
1502 2 : thisMaterial->TausFrontBeamDiffVis = MaterialProps(7);
1503 2 : thisMaterial->ReflFrontBeamDiffVis = MaterialProps(8);
1504 2 : thisMaterial->TausThermal = MaterialProps(9);
1505 2 : thisMaterial->EmissThermalFront = MaterialProps(10);
1506 2 : thisMaterial->EmissThermalBack = MaterialProps(11);
1507 : // Assumes thermal emissivity is the same as thermal absorptance
1508 2 : thisMaterial->AbsorpThermalFront = thisMaterial->EmissThermalFront;
1509 2 : thisMaterial->AbsorpThermalBack = thisMaterial->EmissThermalBack;
1510 2 : thisMaterial->TransThermal = thisMaterial->TausThermal;
1511 :
1512 2 : if (MaterialProps(1) + MaterialProps(2) + MaterialProps(4) >= 1.0) {
1513 0 : ErrorsFound = true;
1514 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1515 0 : ShowContinueError(state,
1516 0 : ipsc->cNumericFieldNames(1) + " + " + ipsc->cNumericFieldNames(2) + " + " + ipsc->cNumericFieldNames(4) + "not < 1.0");
1517 : }
1518 2 : if (MaterialProps(1) + MaterialProps(3) + MaterialProps(5) >= 1.0) {
1519 0 : ErrorsFound = true;
1520 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1521 0 : ShowContinueError(state,
1522 0 : ipsc->cNumericFieldNames(1) + " + " + ipsc->cNumericFieldNames(3) + " + " + ipsc->cNumericFieldNames(5) + "not < 1.0");
1523 : }
1524 2 : if (MaterialProps(6) + MaterialProps(7) + MaterialProps(8) >= 1.0) {
1525 0 : ErrorsFound = true;
1526 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1527 0 : ShowContinueError(state,
1528 0 : ipsc->cNumericFieldNames(6) + " + " + ipsc->cNumericFieldNames(7) + " + " + ipsc->cNumericFieldNames(8) + "not < 1.0");
1529 : }
1530 2 : if (MaterialProps(9) + MaterialProps(10) >= 1.0) {
1531 0 : ErrorsFound = true;
1532 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1533 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " + " + ipsc->cNumericFieldNames(10) + " not < 1.0");
1534 : }
1535 2 : if (MaterialProps(9) + MaterialProps(11) >= 1.0) {
1536 0 : ErrorsFound = true;
1537 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1538 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " + " + ipsc->cNumericFieldNames(11) + " not < 1.0");
1539 : }
1540 :
1541 : } // TotShadesEQL loop
1542 :
1543 : // Window drape materials
1544 :
1545 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Drape:EquivalentLayer";
1546 796 : for (Loop = 1; Loop <= state.dataHeatBal->TotDrapesEQL; ++Loop) {
1547 :
1548 0 : MaterialProps = 0;
1549 :
1550 : // Call Input Get routine to retrieve material data
1551 0 : ip->getObjectItem(state,
1552 0 : state.dataHeatBalMgr->CurrentModuleObject,
1553 : Loop,
1554 : MaterialNames,
1555 : MaterialNumAlpha,
1556 : MaterialProps,
1557 : MaterialNumProp,
1558 : IOStat,
1559 0 : ipsc->lNumericFieldBlanks,
1560 0 : ipsc->lAlphaFieldBlanks,
1561 0 : ipsc->cAlphaFieldNames,
1562 0 : ipsc->cNumericFieldNames);
1563 0 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1564 0 : state.dataHeatBalMgr->UniqueMaterialNames,
1565 0 : MaterialNames(1),
1566 0 : state.dataHeatBalMgr->CurrentModuleObject,
1567 0 : ipsc->cAlphaFieldNames(1),
1568 : ErrorsFound)) {
1569 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1570 0 : continue;
1571 : }
1572 :
1573 0 : ++MaterNum;
1574 0 : auto *thisMaterial = new MaterialChild;
1575 0 : state.dataMaterial->Material(MaterNum) = thisMaterial;
1576 0 : thisMaterial->group = Group::DrapeEquivalentLayer;
1577 :
1578 0 : thisMaterial->Name = MaterialNames(1);
1579 0 : thisMaterial->Roughness = SurfaceRoughness::MediumRough;
1580 0 : thisMaterial->ROnly = true;
1581 :
1582 : // Front side and back side have the same properties
1583 0 : thisMaterial->TausFrontBeamBeam = MaterialProps(1);
1584 0 : thisMaterial->TausBackBeamBeam = MaterialProps(1);
1585 :
1586 0 : thisMaterial->TausFrontBeamDiff = MaterialProps(2);
1587 0 : thisMaterial->TausBackBeamDiff = MaterialProps(3);
1588 :
1589 0 : thisMaterial->ReflFrontBeamDiff = MaterialProps(4);
1590 0 : thisMaterial->ReflBackBeamDiff = MaterialProps(5);
1591 0 : thisMaterial->TausFrontBeamBeamVis = MaterialProps(6);
1592 0 : thisMaterial->TausFrontBeamDiffVis = MaterialProps(7);
1593 0 : thisMaterial->ReflFrontBeamDiffVis = MaterialProps(8);
1594 0 : thisMaterial->TausThermal = MaterialProps(9);
1595 0 : thisMaterial->EmissThermalFront = MaterialProps(10);
1596 0 : thisMaterial->EmissThermalBack = MaterialProps(11);
1597 : // Assumes thermal emissivity is the same as thermal absorptance
1598 0 : thisMaterial->AbsorpThermalFront = thisMaterial->EmissThermalFront;
1599 0 : thisMaterial->AbsorpThermalBack = thisMaterial->EmissThermalBack;
1600 0 : thisMaterial->TransThermal = thisMaterial->TausThermal;
1601 :
1602 0 : if (!ipsc->lNumericFieldBlanks(12) && !ipsc->lNumericFieldBlanks(13)) {
1603 0 : if (MaterialProps(12) != 0.0 && MaterialProps(13) != 0.0) {
1604 0 : thisMaterial->PleatedDrapeWidth = MaterialProps(12);
1605 0 : thisMaterial->PleatedDrapeLength = MaterialProps(13);
1606 0 : thisMaterial->ISPleatedDrape = true;
1607 : }
1608 : } else {
1609 0 : thisMaterial->ISPleatedDrape = false;
1610 : }
1611 0 : if (MaterialProps(1) + MaterialProps(2) + MaterialProps(4) >= 1.0) {
1612 0 : ErrorsFound = true;
1613 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1614 0 : ShowContinueError(state,
1615 0 : ipsc->cNumericFieldNames(1) + " + " + ipsc->cNumericFieldNames(2) + " + " + ipsc->cNumericFieldNames(4) + "not < 1.0");
1616 : }
1617 0 : if (MaterialProps(6) + MaterialProps(7) + MaterialProps(8) >= 1.0) {
1618 0 : ErrorsFound = true;
1619 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1620 0 : ShowContinueError(state,
1621 0 : ipsc->cNumericFieldNames(4) + " + " + ipsc->cNumericFieldNames(5) + " + " + ipsc->cNumericFieldNames(6) + "not < 1.0");
1622 : }
1623 0 : if (MaterialProps(9) + MaterialProps(10) > 1.0) {
1624 0 : ErrorsFound = true;
1625 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1626 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " + " + ipsc->cNumericFieldNames(10) + " not < 1.0");
1627 : }
1628 :
1629 : } // TotDrapesEQL loop
1630 :
1631 : // Window Screen Materials
1632 :
1633 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Screen";
1634 798 : for (Loop = 1; Loop <= state.dataHeatBal->TotScreens; ++Loop) {
1635 :
1636 : // Call GetObjectItem routine to retrieve material data
1637 6 : ip->getObjectItem(state,
1638 2 : state.dataHeatBalMgr->CurrentModuleObject,
1639 : Loop,
1640 : MaterialNames,
1641 : MaterialNumAlpha,
1642 : MaterialProps,
1643 : MaterialNumProp,
1644 : IOStat,
1645 2 : ipsc->lNumericFieldBlanks,
1646 2 : ipsc->lAlphaFieldBlanks,
1647 2 : ipsc->cAlphaFieldNames,
1648 2 : ipsc->cNumericFieldNames);
1649 4 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1650 2 : state.dataHeatBalMgr->UniqueMaterialNames,
1651 2 : MaterialNames(1),
1652 2 : state.dataHeatBalMgr->CurrentModuleObject,
1653 2 : ipsc->cAlphaFieldNames(1),
1654 : ErrorsFound)) {
1655 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1656 0 : continue;
1657 : }
1658 :
1659 2 : ++MaterNum;
1660 2 : auto *matScreen = new MaterialScreen;
1661 2 : state.dataMaterial->Material(MaterNum) = matScreen;
1662 :
1663 : // Load the material derived type from the input data.
1664 :
1665 2 : matScreen->Name = MaterialNames(1);
1666 2 : matScreen->bmRefModel =
1667 2 : static_cast<ScreenBeamReflectanceModel>(getEnumValue(screenBeamReflectanceModelNamesUC, Util::makeUPPER(MaterialNames(2))));
1668 2 : if (matScreen->bmRefModel == ScreenBeamReflectanceModel::Invalid) {
1669 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
1670 0 : ShowContinueError(
1671 : state,
1672 0 : format("{}=\"{}\", must be one of DoNotModel, ModelAsDirectBeam or ModelAsDiffuse.", ipsc->cAlphaFieldNames(2), MaterialNames(2)));
1673 0 : ErrorsFound = true;
1674 : }
1675 2 : matScreen->Roughness = SurfaceRoughness::MediumRough;
1676 2 : matScreen->ShadeRef = MaterialProps(1);
1677 2 : if (matScreen->ShadeRef < 0.0 || matScreen->ShadeRef > 1.0) {
1678 0 : ErrorsFound = true;
1679 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1680 0 : ShowContinueError(state, ipsc->cNumericFieldNames(1) + " must be >= 0 and <= 1");
1681 : }
1682 2 : matScreen->ShadeRefVis = MaterialProps(2);
1683 2 : if (matScreen->ShadeRefVis < 0.0 || matScreen->ShadeRefVis > 1.0) {
1684 0 : ErrorsFound = true;
1685 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1686 0 : ShowContinueError(state, ipsc->cNumericFieldNames(2) + " must be >= 0 and <= 1 for material " + matScreen->Name + '.');
1687 : }
1688 2 : matScreen->AbsorpThermal = MaterialProps(3);
1689 2 : matScreen->AbsorpThermalInput = MaterialProps(3);
1690 2 : if (matScreen->AbsorpThermal < 0.0 || matScreen->AbsorpThermal > 1.0) {
1691 0 : ErrorsFound = true;
1692 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1693 0 : ShowContinueError(state, ipsc->cNumericFieldNames(3) + " must be >= 0 and <= 1");
1694 : }
1695 2 : matScreen->Conductivity = MaterialProps(4);
1696 2 : matScreen->Thickness = MaterialProps(6); // thickness = diameter
1697 :
1698 2 : if (MaterialProps(5) > 0.0) {
1699 : // Screens(ScNum)%ScreenDiameterToSpacingRatio = MaterialProps(6)/MaterialProps(5) or
1700 : // 1-SQRT(dataMaterial.Material(MaterNum)%Trans
1701 2 : if (MaterialProps(6) / MaterialProps(5) >= 1.0) {
1702 0 : ErrorsFound = true;
1703 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1704 0 : ShowContinueError(state, ipsc->cNumericFieldNames(6) + " must be less than " + ipsc->cNumericFieldNames(5));
1705 : } else {
1706 : // Calculate direct normal transmittance (open area fraction)
1707 2 : matScreen->Trans = pow_2(1.0 - MaterialProps(6) / MaterialProps(5));
1708 : }
1709 : } else {
1710 0 : ErrorsFound = true;
1711 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1712 0 : ShowContinueError(state, ipsc->cNumericFieldNames(5) + " must be > 0.");
1713 0 : MaterialProps(5) = 0.000000001;
1714 : }
1715 :
1716 2 : if (MaterialProps(6) <= 0.0) {
1717 0 : ErrorsFound = true;
1718 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1719 0 : ShowContinueError(state, ipsc->cNumericFieldNames(6) + " must be > 0.");
1720 : }
1721 :
1722 : // Modify reflectance to account for the open area in the screen assembly
1723 2 : matScreen->ShadeRef *= (1.0 - matScreen->Trans);
1724 2 : matScreen->ShadeRefVis *= (1.0 - matScreen->Trans);
1725 :
1726 2 : matScreen->toGlassDist = MaterialProps(7);
1727 2 : if (matScreen->toGlassDist < 0.001 || matScreen->toGlassDist > 1.0) {
1728 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1729 0 : ShowContinueError(state, ipsc->cNumericFieldNames(7) + " must be greater than or equal to 0.001 and less than or equal to 1.");
1730 : }
1731 :
1732 2 : matScreen->topOpeningMult = MaterialProps(8);
1733 2 : if (matScreen->topOpeningMult < 0.0 || matScreen->topOpeningMult > 1.0) {
1734 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1735 0 : ShowContinueError(state, ipsc->cNumericFieldNames(8) + " must be greater than or equal to 0 and less than or equal to 1.");
1736 : }
1737 :
1738 2 : matScreen->bottomOpeningMult = MaterialProps(9);
1739 2 : if (matScreen->bottomOpeningMult < 0.0 || matScreen->bottomOpeningMult > 1.0) {
1740 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1741 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " must be greater than or equal to 0 and less than or equal to 1.");
1742 : }
1743 :
1744 2 : matScreen->leftOpeningMult = MaterialProps(10);
1745 2 : if (matScreen->leftOpeningMult < 0.0 || matScreen->leftOpeningMult > 1.0) {
1746 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1747 0 : ShowContinueError(state, ipsc->cNumericFieldNames(10) + " must be greater than or equal to 0 and less than or equal to 1.");
1748 : }
1749 :
1750 2 : matScreen->rightOpeningMult = MaterialProps(11);
1751 2 : if (matScreen->rightOpeningMult < 0.0 || matScreen->rightOpeningMult > 1.0) {
1752 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1753 0 : ShowContinueError(state, ipsc->cNumericFieldNames(11) + " must be greater than or equal to 0 and less than or equal to 1.");
1754 : }
1755 :
1756 2 : matScreen->mapDegResolution = MaterialProps(12);
1757 2 : if (matScreen->mapDegResolution < 0 || matScreen->mapDegResolution > 5 || matScreen->mapDegResolution == 4) {
1758 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1759 0 : ShowContinueError(state, ipsc->cNumericFieldNames(12) + " must be 0, 1, 2, 3, or 5.");
1760 0 : ErrorsFound = true;
1761 : }
1762 :
1763 : // Default air flow permeability to open area fraction
1764 2 : matScreen->airFlowPermeability = matScreen->Trans;
1765 2 : matScreen->TransThermal = matScreen->Trans;
1766 2 : matScreen->TransVis = matScreen->Trans;
1767 :
1768 2 : matScreen->ROnly = true;
1769 :
1770 : // Calculate absorptance accounting for the open area in the screen assembly (used only in CreateShadedWindowConstruction)
1771 2 : matScreen->AbsorpSolar = max(0.0, 1.0 - matScreen->Trans - matScreen->ShadeRef);
1772 2 : matScreen->AbsorpSolarInput = matScreen->AbsorpSolar;
1773 2 : matScreen->AbsorpVisible = max(0.0, 1.0 - matScreen->TransVis - matScreen->ShadeRefVis);
1774 2 : matScreen->AbsorpVisibleInput = matScreen->AbsorpVisible;
1775 2 : matScreen->AbsorpThermal *= (1.0 - matScreen->Trans);
1776 2 : matScreen->AbsorpThermalInput = matScreen->AbsorpThermal;
1777 :
1778 2 : if (matScreen->Conductivity > 0.0) {
1779 2 : state.dataHeatBal->NominalR(MaterNum) = (1.0 - matScreen->Trans) * matScreen->Thickness / matScreen->Conductivity;
1780 : } else {
1781 0 : state.dataHeatBal->NominalR(MaterNum) = 1.0;
1782 0 : ShowWarningError(
1783 : state,
1784 0 : "Conductivity for material=\"" + matScreen->Name +
1785 : "\" must be greater than 0 for calculating Nominal R-value, Nominal R is defaulted to 1 and the simulation continues.");
1786 : }
1787 :
1788 2 : if (matScreen->Trans + matScreen->ShadeRef >= 1.0) {
1789 0 : ErrorsFound = true;
1790 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1791 0 : ShowContinueError(state, "Calculated solar transmittance + solar reflectance not < 1.0");
1792 0 : ShowContinueError(state, "See Engineering Reference for calculation procedure for solar transmittance.");
1793 : }
1794 :
1795 2 : if (matScreen->TransVis + matScreen->ShadeRefVis >= 1.0) {
1796 0 : ErrorsFound = true;
1797 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1798 0 : ShowContinueError(state, "Calculated visible transmittance + visible reflectance not < 1.0");
1799 0 : ShowContinueError(state, "See Engineering Reference for calculation procedure for visible solar transmittance.");
1800 : }
1801 :
1802 2 : if (matScreen->TransThermal + matScreen->AbsorpThermal >= 1.0) {
1803 0 : ErrorsFound = true;
1804 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1805 0 : ShowContinueError(state, "Thermal hemispherical emissivity plus open area fraction (1-diameter/spacing)**2 not < 1.0");
1806 : }
1807 : }
1808 :
1809 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Screen:EquivalentLayer";
1810 797 : for (Loop = 1; Loop <= state.dataHeatBal->TotScreensEQL; ++Loop) {
1811 :
1812 1 : MaterialProps = 0;
1813 :
1814 : // Call GetObjectItem routine to retrieve material data
1815 3 : ip->getObjectItem(state,
1816 1 : state.dataHeatBalMgr->CurrentModuleObject,
1817 : Loop,
1818 : MaterialNames,
1819 : MaterialNumAlpha,
1820 : MaterialProps,
1821 : MaterialNumProp,
1822 : IOStat,
1823 1 : ipsc->lNumericFieldBlanks,
1824 1 : ipsc->lAlphaFieldBlanks,
1825 1 : ipsc->cAlphaFieldNames,
1826 1 : ipsc->cNumericFieldNames);
1827 2 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1828 1 : state.dataHeatBalMgr->UniqueMaterialNames,
1829 1 : MaterialNames(1),
1830 1 : state.dataHeatBalMgr->CurrentModuleObject,
1831 1 : ipsc->cAlphaFieldNames(1),
1832 : ErrorsFound)) {
1833 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1834 0 : continue;
1835 : }
1836 :
1837 1 : ++MaterNum;
1838 1 : auto *matScreen = new MaterialChild;
1839 1 : state.dataMaterial->Material(MaterNum) = matScreen;
1840 1 : matScreen->group = Group::ScreenEquivalentLayer;
1841 :
1842 : // Load the material derived type from the input data.
1843 : // WindowMaterial:Screen:EquivalentLayer,
1844 1 : matScreen->Name = MaterialNames(1);
1845 1 : matScreen->Roughness = SurfaceRoughness::MediumRough;
1846 1 : matScreen->ROnly = true;
1847 1 : matScreen->TausFrontBeamBeam = MaterialProps(1);
1848 1 : matScreen->TausBackBeamBeam = MaterialProps(1);
1849 1 : matScreen->TausFrontBeamDiff = MaterialProps(2);
1850 1 : matScreen->TausBackBeamDiff = MaterialProps(2);
1851 1 : matScreen->ReflFrontBeamDiff = MaterialProps(3);
1852 1 : matScreen->ReflBackBeamDiff = MaterialProps(3);
1853 1 : matScreen->TausFrontBeamBeamVis = MaterialProps(4);
1854 1 : matScreen->TausFrontBeamDiffVis = MaterialProps(5);
1855 1 : matScreen->ReflFrontDiffDiffVis = MaterialProps(6);
1856 1 : matScreen->TausThermal = MaterialProps(7);
1857 1 : matScreen->EmissThermalFront = MaterialProps(8);
1858 1 : matScreen->EmissThermalBack = MaterialProps(8);
1859 :
1860 : // Assumes thermal emissivity is the same as thermal absorptance
1861 1 : matScreen->AbsorpThermalFront = matScreen->EmissThermalFront;
1862 1 : matScreen->AbsorpThermalBack = matScreen->EmissThermalBack;
1863 1 : matScreen->TransThermal = matScreen->TausThermal;
1864 :
1865 1 : if (MaterialProps(3) < 0.0 || MaterialProps(3) > 1.0) {
1866 0 : ErrorsFound = true;
1867 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1868 0 : ShowContinueError(state, ipsc->cNumericFieldNames(3) + " must be >= 0 and <= 1");
1869 : }
1870 :
1871 1 : if (MaterialProps(6) < 0.0 || MaterialProps(6) > 1.0) {
1872 0 : ErrorsFound = true;
1873 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1874 0 : ShowContinueError(state, ipsc->cNumericFieldNames(6) + " must be >= 0 and <= 1 for material " + matScreen->Name + '.');
1875 : }
1876 :
1877 1 : if (!ipsc->lNumericFieldBlanks(9)) {
1878 1 : if (MaterialProps(9) > 0.00001) {
1879 1 : matScreen->ScreenWireSpacing = MaterialProps(9); // screen wire spacing
1880 : } else {
1881 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1882 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " must be > 0.");
1883 0 : ShowContinueError(state, "...Setting screen wire spacing to a default value of 0.025m and simulation continues.");
1884 0 : matScreen->ScreenWireSpacing = 0.025;
1885 : }
1886 : }
1887 :
1888 1 : if (!ipsc->lNumericFieldBlanks(10)) {
1889 1 : if (MaterialProps(10) > 0.00001 && MaterialProps(10) < matScreen->ScreenWireSpacing) {
1890 1 : matScreen->ScreenWireDiameter = MaterialProps(10); // screen wire spacing
1891 : } else {
1892 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value.");
1893 0 : ShowContinueError(state, ipsc->cNumericFieldNames(10) + " must be > 0.");
1894 0 : ShowContinueError(state, "...Setting screen wire diameter to a default value of 0.005m and simulation continues.");
1895 0 : matScreen->ScreenWireDiameter = 0.005;
1896 : }
1897 : }
1898 :
1899 1 : if (matScreen->ScreenWireSpacing > 0.0) {
1900 1 : if (matScreen->ScreenWireDiameter / matScreen->ScreenWireSpacing >= 1.0) {
1901 0 : ErrorsFound = true;
1902 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1903 0 : ShowContinueError(state, ipsc->cNumericFieldNames(10) + " must be less than " + ipsc->cNumericFieldNames(9));
1904 : } else {
1905 : // Calculate direct normal transmittance (open area fraction)
1906 1 : Openness = pow_2(1.0 - matScreen->ScreenWireDiameter / matScreen->ScreenWireSpacing);
1907 1 : if ((matScreen->TausFrontBeamBeam - Openness) / Openness > 0.01) {
1908 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", screen openness specified.");
1909 0 : ShowContinueError(state, ipsc->cNumericFieldNames(1) + " is > 1.0% of the value calculated from input fields:");
1910 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " and " + (ipsc->cNumericFieldNames(10)));
1911 0 : ShowContinueError(state, " using the formula (1-diameter/spacing)**2");
1912 0 : ShowContinueError(state, " ...the screen diameter is recalculated from the material openness specified ");
1913 0 : ShowContinueError(state, " ...and wire spacing using the formula = wire spacing * (1.0 - SQRT(Opennes))");
1914 0 : matScreen->ScreenWireDiameter = matScreen->ScreenWireSpacing * (1.0 - std::sqrt(matScreen->TausFrontBeamBeam));
1915 0 : ShowContinueError(state, format(" ...Recalculated {}={:.4R} m", ipsc->cNumericFieldNames(10), matScreen->ScreenWireDiameter));
1916 : }
1917 : }
1918 : }
1919 :
1920 1 : if (matScreen->TausFrontBeamBeam + matScreen->ReflFrontBeamDiff >= 1.0) {
1921 0 : ErrorsFound = true;
1922 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1923 0 : ShowContinueError(state, "Calculated solar transmittance + solar reflectance not < 1.0");
1924 0 : ShowContinueError(state, "See Engineering Reference for calculation procedure for solar transmittance.");
1925 : }
1926 :
1927 1 : if (matScreen->TausFrontBeamBeamVis + matScreen->ReflFrontDiffDiffVis >= 1.0) {
1928 0 : ErrorsFound = true;
1929 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1930 0 : ShowContinueError(state, "Calculated visible transmittance + visible reflectance not < 1.0");
1931 0 : ShowContinueError(state, "See Engineering Reference for calculation procedure for visible solar transmittance.");
1932 : }
1933 1 : if (matScreen->TransThermal + matScreen->AbsorpThermal >= 1.0) {
1934 0 : ErrorsFound = true;
1935 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
1936 0 : ShowContinueError(state, "Thermal hemispherical emissivity plus open area fraction (1-diameter/spacing)**2 not < 1.0");
1937 : }
1938 :
1939 : } // TotScreensEQL loop
1940 :
1941 : // Window Blind Materials
1942 796 : if ((state.dataHeatBal->TotBlindsEQL == 0) && (state.dataHeatBal->TotBlinds == 0)) {
1943 778 : state.dataSurface->actualMaxSlatAngs = 1; // first slot is used for shades
1944 : }
1945 :
1946 796 : if (state.dataHeatBal->TotBlinds > 0) {
1947 18 : state.dataMaterial->Blind.allocate(state.dataHeatBal->TotBlinds); // Allocate the array Size to the number of blinds
1948 : }
1949 :
1950 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Blind";
1951 814 : for (Loop = 1; Loop <= state.dataHeatBal->TotBlinds; ++Loop) {
1952 :
1953 : // Call Input Get routine to retrieve material data
1954 54 : ip->getObjectItem(state,
1955 18 : state.dataHeatBalMgr->CurrentModuleObject,
1956 : Loop,
1957 : MaterialNames,
1958 : MaterialNumAlpha,
1959 : MaterialProps,
1960 : MaterialNumProp,
1961 : IOStat,
1962 18 : ipsc->lNumericFieldBlanks,
1963 18 : ipsc->lAlphaFieldBlanks,
1964 18 : ipsc->cAlphaFieldNames,
1965 18 : ipsc->cNumericFieldNames);
1966 36 : if (GlobalNames::VerifyUniqueInterObjectName(state,
1967 18 : state.dataHeatBalMgr->UniqueMaterialNames,
1968 18 : MaterialNames(1),
1969 18 : state.dataHeatBalMgr->CurrentModuleObject,
1970 18 : ipsc->cAlphaFieldNames(1),
1971 : ErrorsFound)) {
1972 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
1973 0 : continue;
1974 : }
1975 :
1976 18 : ++MaterNum;
1977 18 : auto *thisMaterial = new MaterialChild;
1978 18 : state.dataMaterial->Material(MaterNum) = thisMaterial;
1979 18 : thisMaterial->group = Group::WindowBlind;
1980 :
1981 : // Load the material derived type from the input data.
1982 :
1983 18 : thisMaterial->Name = MaterialNames(1);
1984 18 : state.dataMaterial->Blind(Loop).Name = MaterialNames(1);
1985 18 : thisMaterial->Roughness = SurfaceRoughness::Rough;
1986 18 : thisMaterial->BlindDataPtr = Loop;
1987 18 : thisMaterial->ROnly = true;
1988 :
1989 18 : state.dataMaterial->Blind(Loop).MaterialNumber = MaterNum;
1990 18 : if (Util::SameString(MaterialNames(2), "Horizontal")) {
1991 18 : state.dataMaterial->Blind(Loop).SlatOrientation = DataWindowEquivalentLayer::Orientation::Horizontal;
1992 0 : } else if (Util::SameString(MaterialNames(2), "Vertical")) {
1993 0 : state.dataMaterial->Blind(Loop).SlatOrientation = DataWindowEquivalentLayer::Orientation::Vertical;
1994 : }
1995 18 : state.dataMaterial->Blind(Loop).SlatWidth = MaterialProps(1);
1996 18 : state.dataMaterial->Blind(Loop).SlatSeparation = MaterialProps(2);
1997 18 : state.dataMaterial->Blind(Loop).SlatThickness = MaterialProps(3);
1998 18 : state.dataMaterial->Blind(Loop).SlatAngle = MaterialProps(4);
1999 18 : state.dataMaterial->Blind(Loop).SlatConductivity = MaterialProps(5);
2000 18 : state.dataMaterial->Blind(Loop).SlatTransSolBeamDiff = MaterialProps(6);
2001 18 : state.dataMaterial->Blind(Loop).SlatFrontReflSolBeamDiff = MaterialProps(7);
2002 18 : state.dataMaterial->Blind(Loop).SlatBackReflSolBeamDiff = MaterialProps(8);
2003 18 : state.dataMaterial->Blind(Loop).SlatTransSolDiffDiff = MaterialProps(9);
2004 18 : state.dataMaterial->Blind(Loop).SlatFrontReflSolDiffDiff = MaterialProps(10);
2005 18 : state.dataMaterial->Blind(Loop).SlatBackReflSolDiffDiff = MaterialProps(11);
2006 18 : state.dataMaterial->Blind(Loop).SlatTransVisBeamDiff = MaterialProps(12);
2007 18 : state.dataMaterial->Blind(Loop).SlatFrontReflVisBeamDiff = MaterialProps(13);
2008 18 : state.dataMaterial->Blind(Loop).SlatBackReflVisBeamDiff = MaterialProps(14);
2009 18 : state.dataMaterial->Blind(Loop).SlatTransVisDiffDiff = MaterialProps(15);
2010 18 : state.dataMaterial->Blind(Loop).SlatFrontReflVisDiffDiff = MaterialProps(16);
2011 18 : state.dataMaterial->Blind(Loop).SlatBackReflVisDiffDiff = MaterialProps(17);
2012 18 : state.dataMaterial->Blind(Loop).SlatTransIR = MaterialProps(18);
2013 18 : state.dataMaterial->Blind(Loop).SlatFrontEmissIR = MaterialProps(19);
2014 18 : state.dataMaterial->Blind(Loop).SlatBackEmissIR = MaterialProps(20);
2015 18 : state.dataMaterial->Blind(Loop).BlindToGlassDist = MaterialProps(21);
2016 18 : state.dataMaterial->Blind(Loop).BlindTopOpeningMult = MaterialProps(22);
2017 18 : state.dataMaterial->Blind(Loop).BlindBottomOpeningMult = MaterialProps(23);
2018 18 : state.dataMaterial->Blind(Loop).BlindLeftOpeningMult = MaterialProps(24);
2019 18 : state.dataMaterial->Blind(Loop).BlindRightOpeningMult = MaterialProps(25);
2020 18 : state.dataMaterial->Blind(Loop).MinSlatAngle = MaterialProps(26);
2021 18 : state.dataMaterial->Blind(Loop).MaxSlatAngle = MaterialProps(27);
2022 :
2023 : // TH 2/11/2010. For CR 8010
2024 : // By default all blinds have fixed slat angle, new blinds with variable slat angle are created if
2025 : // they are used with window shading controls that adjust slat angles like ScheduledSlatAngle or BlockBeamSolar
2026 18 : state.dataMaterial->Blind(Loop).SlatAngleType = DataWindowEquivalentLayer::AngleType::Fixed;
2027 :
2028 18 : if (state.dataMaterial->Blind(Loop).SlatWidth < state.dataMaterial->Blind(Loop).SlatSeparation) {
2029 0 : ShowWarningError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Slat Angles/Widths");
2030 0 : ShowContinueError(state,
2031 0 : format("{} [{:.2R}] is less than {} [{:.2R}].",
2032 0 : ipsc->cNumericFieldNames(1),
2033 0 : state.dataMaterial->Blind(Loop).SlatWidth,
2034 0 : ipsc->cNumericFieldNames(2),
2035 0 : state.dataMaterial->Blind(Loop).SlatSeparation));
2036 0 : ShowContinueError(state, "This will allow direct beam to be transmitted when Slat angle = 0.");
2037 : }
2038 :
2039 18 : if (!Util::SameString(MaterialNames(2), "Horizontal") && !Util::SameString(MaterialNames(2), "Vertical")) {
2040 0 : ErrorsFound = true;
2041 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value");
2042 0 : ShowContinueError(state, ipsc->cAlphaFieldNames(2) + "=\"" + MaterialNames(2) + "\", must be Horizontal or Vertical.");
2043 : }
2044 :
2045 18 : if ((MaterialProps(6) + MaterialProps(7) >= 1.0)) {
2046 0 : ErrorsFound = true;
2047 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2048 0 : ShowContinueError(state, ipsc->cNumericFieldNames(6) + " + " + ipsc->cNumericFieldNames(7) + " not < 1.0");
2049 : }
2050 18 : if ((MaterialProps(6) + MaterialProps(8) >= 1.0)) {
2051 0 : ErrorsFound = true;
2052 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2053 0 : ShowContinueError(state, ipsc->cNumericFieldNames(6) + " + " + ipsc->cNumericFieldNames(8) + " not < 1.0");
2054 : }
2055 :
2056 18 : if ((MaterialProps(9) + MaterialProps(10) >= 1.0)) {
2057 0 : ErrorsFound = true;
2058 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2059 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " + " + ipsc->cNumericFieldNames(10) + " not < 1.0");
2060 : }
2061 18 : if ((MaterialProps(9) + MaterialProps(11) >= 1.0)) {
2062 0 : ErrorsFound = true;
2063 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2064 0 : ShowContinueError(state, ipsc->cNumericFieldNames(9) + " + " + ipsc->cNumericFieldNames(11) + " not < 1.0");
2065 : }
2066 :
2067 18 : if ((MaterialProps(12) + MaterialProps(13) >= 1.0) || (MaterialProps(12) + MaterialProps(14) >= 1.0)) {
2068 0 : ErrorsFound = true;
2069 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2070 0 : ShowContinueError(state, ipsc->cNumericFieldNames(12) + " + " + ipsc->cNumericFieldNames(13) + " not < 1.0 OR");
2071 0 : ShowContinueError(state, ipsc->cNumericFieldNames(12) + " + " + ipsc->cNumericFieldNames(14) + " not < 1.0");
2072 : }
2073 :
2074 18 : if ((MaterialProps(12) + MaterialProps(13) >= 1.0)) {
2075 0 : ErrorsFound = true;
2076 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2077 0 : ShowContinueError(state, ipsc->cNumericFieldNames(12) + " + " + ipsc->cNumericFieldNames(13) + " not < 1.0");
2078 : }
2079 18 : if ((MaterialProps(12) + MaterialProps(14) >= 1.0)) {
2080 0 : ErrorsFound = true;
2081 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2082 0 : ShowContinueError(state, ipsc->cNumericFieldNames(12) + " + " + ipsc->cNumericFieldNames(14) + " not < 1.0");
2083 : }
2084 :
2085 18 : if ((MaterialProps(15) + MaterialProps(16) >= 1.0)) {
2086 0 : ErrorsFound = true;
2087 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2088 0 : ShowContinueError(state, ipsc->cNumericFieldNames(15) + " + " + ipsc->cNumericFieldNames(16) + " not < 1.0");
2089 : }
2090 18 : if ((MaterialProps(15) + MaterialProps(17) >= 1.0)) {
2091 0 : ErrorsFound = true;
2092 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2093 0 : ShowContinueError(state, ipsc->cNumericFieldNames(15) + " + " + ipsc->cNumericFieldNames(17) + " not < 1.0");
2094 : }
2095 :
2096 : // Require that beam and diffuse properties be the same
2097 18 : if (std::abs(MaterialProps(9) - MaterialProps(6)) > 1.e-5) {
2098 0 : ErrorsFound = true;
2099 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2100 0 : ShowContinueError(state, ipsc->cNumericFieldNames(6) + " must equal " + ipsc->cNumericFieldNames(9));
2101 : }
2102 :
2103 18 : if (std::abs(MaterialProps(10) - MaterialProps(7)) > 1.e-5) {
2104 0 : ErrorsFound = true;
2105 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2106 0 : ShowContinueError(state, ipsc->cNumericFieldNames(7) + " must equal " + ipsc->cNumericFieldNames(10));
2107 : }
2108 :
2109 18 : if (std::abs(MaterialProps(11) - MaterialProps(8)) > 1.e-5) {
2110 0 : ErrorsFound = true;
2111 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2112 0 : ShowContinueError(state, ipsc->cNumericFieldNames(8) + " must equal " + ipsc->cNumericFieldNames(11));
2113 : }
2114 :
2115 18 : if (std::abs(MaterialProps(15) - MaterialProps(12)) > 1.e-5) {
2116 0 : ErrorsFound = true;
2117 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2118 0 : ShowContinueError(state, ipsc->cNumericFieldNames(12) + " must equal " + ipsc->cNumericFieldNames(15));
2119 : }
2120 :
2121 18 : if (std::abs(MaterialProps(16) - MaterialProps(13)) > 1.e-5) {
2122 0 : ErrorsFound = true;
2123 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2124 0 : ShowContinueError(state, ipsc->cNumericFieldNames(13) + " must equal " + ipsc->cNumericFieldNames(16));
2125 : }
2126 :
2127 18 : if (std::abs(MaterialProps(17) - MaterialProps(14)) > 1.e-5) {
2128 0 : ErrorsFound = true;
2129 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2130 0 : ShowContinueError(state, ipsc->cNumericFieldNames(14) + " must equal " + ipsc->cNumericFieldNames(17));
2131 : }
2132 :
2133 18 : if ((MaterialProps(18) + MaterialProps(19) >= 1.0)) {
2134 0 : ErrorsFound = true;
2135 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2136 0 : ShowContinueError(state, ipsc->cNumericFieldNames(18) + " + " + ipsc->cNumericFieldNames(19) + " not < 1.0");
2137 : }
2138 18 : if ((MaterialProps(18) + MaterialProps(20) >= 1.0)) {
2139 0 : ErrorsFound = true;
2140 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2141 0 : ShowContinueError(state, ipsc->cNumericFieldNames(18) + " + " + ipsc->cNumericFieldNames(20) + " not < 1.0");
2142 : }
2143 :
2144 18 : if (state.dataMaterial->Blind(Loop).BlindToGlassDist < 0.5 * state.dataMaterial->Blind(Loop).SlatWidth) {
2145 0 : ErrorsFound = true;
2146 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2147 0 : ShowContinueError(state, ipsc->cNumericFieldNames(21) + " is less than half of the " + ipsc->cNumericFieldNames(1));
2148 : }
2149 :
2150 : // Minimum and maximum slat angles allowed by slat geometry
2151 18 : if (state.dataMaterial->Blind(Loop).SlatWidth > state.dataMaterial->Blind(Loop).SlatSeparation) {
2152 18 : MinSlatAngGeom = std::asin(state.dataMaterial->Blind(Loop).SlatThickness /
2153 18 : (state.dataMaterial->Blind(Loop).SlatThickness + state.dataMaterial->Blind(Loop).SlatSeparation)) /
2154 : Constant::DegToRadians;
2155 : } else {
2156 0 : MinSlatAngGeom = 0.0;
2157 : }
2158 18 : MaxSlatAngGeom = 180.0 - MinSlatAngGeom;
2159 :
2160 : // Error if input slat angle not in range allowed by slat geometry
2161 18 : if ((state.dataMaterial->Blind(Loop).SlatSeparation + state.dataMaterial->Blind(Loop).SlatThickness) <
2162 18 : state.dataMaterial->Blind(Loop).SlatWidth) {
2163 18 : if (state.dataMaterial->Blind(Loop).SlatAngle < MinSlatAngGeom) {
2164 0 : ErrorsFound = true;
2165 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2166 0 : ShowContinueError(state,
2167 0 : format("{}=[{:.1R}], is less than smallest allowed by slat dimensions and spacing, [{:.1R}] deg.",
2168 0 : ipsc->cNumericFieldNames(4),
2169 0 : state.dataMaterial->Blind(Loop).SlatAngle,
2170 : MinSlatAngGeom));
2171 18 : } else if (state.dataMaterial->Blind(Loop).SlatAngle > MaxSlatAngGeom) {
2172 0 : ErrorsFound = true;
2173 0 : ShowSevereError(state, state.dataHeatBalMgr->CurrentModuleObject + "=\"" + MaterialNames(1) + "\", Illegal value combination.");
2174 0 : ShowContinueError(state,
2175 0 : format("{}=[{:.1R}], is greater than largest allowed by slat dimensions and spacing, [{:.1R}] deg.",
2176 0 : ipsc->cNumericFieldNames(4),
2177 0 : state.dataMaterial->Blind(Loop).SlatAngle,
2178 : MinSlatAngGeom));
2179 : }
2180 : }
2181 :
2182 : // By default all Blinds are "fixed" slats. Only with Shading Control is one considered variable and this check
2183 : // is now done when that happens. 9.3.2009 LKL
2184 :
2185 : // IF(Blind(Loop)%SlatAngleType == VariableSlats) THEN
2186 : // ! Error if maximum slat angle less than minimum
2187 : // IF(Blind(Loop)%MaxSlatAngle < Blind(Loop)%MinSlatAngle) THEN
2188 : // ErrorsFound = .TRUE.
2189 : // CALL ShowSevereError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//'="'//TRIM(MaterialNames(1))//'", Illegal value
2190 : // combination.') CALL ShowContinueError(state,
2191 : // TRIM(cNumericFieldNames(26))//'=['//TRIM(RoundSigDigits(Blind(Loop)%MinSlatAngle,1))// &
2192 : // '], is greater than '//TRIM(cNumericFieldNames(27))//'=['// &
2193 : // TRIM(RoundSigDigits(Blind(Loop)%MaxSlatAngle,1))//'] deg.')
2194 : // END IF
2195 : // ! Error if input slat angle not in input min/max range
2196 : // IF(Blind(Loop)%MaxSlatAngle > Blind(Loop)%MinSlatAngle .AND. (Blind(Loop)%SlatAngle < Blind(Loop)%MinSlatAngle &
2197 : // .OR. Blind(Loop)%SlatAngle > Blind(Loop)%MaxSlatAngle)) THEN
2198 : // ErrorsFound = .TRUE.
2199 : // CALL ShowSevereError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//'="'//TRIM(MaterialNames(1))//'", Illegal value
2200 : // combination.') CALL ShowContinueError(state, TRIM(cNumericFieldNames(4))//'=['//TRIM(RoundSigDigits(Blind(Loop)%SlatAngle,1))//
2201 : // &
2202 : // '] is outside of the input min/max range, min=['//TRIM(RoundSigDigits(Blind(Loop)%MinSlatAngle,1))// &
2203 : // '], max=['//TRIM(RoundSigDigits(Blind(Loop)%MaxSlatAngle,1))//'] deg.')
2204 : // END IF
2205 : // ! Error if input minimum slat angle is less than that allowed by slat geometry
2206 : // IF(Blind(Loop)%MinSlatAngle < MinSlatAngGeom) THEN
2207 : // CALL ShowSevereError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//'="'//TRIM(MaterialNames(1))//'", Illegal value
2208 : // combination.') CALL ShowContinueError(state,
2209 : // TRIM(cNumericFieldNames(26))//'=['//TRIM(RoundSigDigits(Blind(Loop)%MinSlatAngle,1))// &
2210 : // '] is less than the smallest allowed by slat dimensions and spacing, min=['// &
2211 : // TRIM(RoundSigDigits(MinSlatAngGeom,1))//'] deg.')
2212 : // CALL ShowContinueError(state, 'Minimum Slat Angle will be set to '//TRIM(RoundSigDigits(MinSlatAngGeom,1))//' deg.')
2213 : // Blind(Loop)%MinSlatAngle = MinSlatAngGeom
2214 : // END IF
2215 : // ! Error if input maximum slat angle is greater than that allowed by slat geometry
2216 : // IF(Blind(Loop)%MaxSlatAngle > MaxSlatAngGeom) THEN
2217 : // CALL ShowWarningError(state, TRIM(state.dataHeatBalMgr->CurrentModuleObject)//'="'//TRIM(MaterialNames(1))//'", Illegal value
2218 : // combination.') CALL ShowContinueError(state,
2219 : // TRIM(cNumericFieldNames(27))//'=['//TRIM(RoundSigDigits(Blind(Loop)%MaxSlatAngle,1))// &
2220 : // '] is greater than the largest allowed by slat dimensions and spacing, ['// &
2221 : // TRIM(RoundSigDigits(MaxSlatAngGeom,1))//'] deg.')
2222 : // CALL ShowContinueError(state, 'Maximum Slat Angle will be set to '//TRIM(RoundSigDigits(MaxSlatAngGeom,1))//' deg.')
2223 : // Blind(Loop)%MaxSlatAngle = MaxSlatAngGeom
2224 : // END IF
2225 : // END IF ! End of check if slat angle is variable
2226 : }
2227 :
2228 : // Window Blind Materials for EquivalentLayer Model
2229 :
2230 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:Blind:EquivalentLayer";
2231 796 : for (Loop = 1; Loop <= state.dataHeatBal->TotBlindsEQL; ++Loop) {
2232 :
2233 : // Call Input Get routine to retrieve material data
2234 0 : ip->getObjectItem(state,
2235 0 : state.dataHeatBalMgr->CurrentModuleObject,
2236 : Loop,
2237 : MaterialNames,
2238 : MaterialNumAlpha,
2239 : MaterialProps,
2240 : MaterialNumProp,
2241 : IOStat,
2242 0 : ipsc->lNumericFieldBlanks,
2243 0 : ipsc->lAlphaFieldBlanks,
2244 0 : ipsc->cAlphaFieldNames,
2245 0 : ipsc->cNumericFieldNames);
2246 0 : if (GlobalNames::VerifyUniqueInterObjectName(state,
2247 0 : state.dataHeatBalMgr->UniqueMaterialNames,
2248 0 : MaterialNames(1),
2249 0 : state.dataHeatBalMgr->CurrentModuleObject,
2250 0 : ipsc->cAlphaFieldNames(1),
2251 : ErrorsFound)) {
2252 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
2253 0 : continue;
2254 : }
2255 :
2256 0 : ++MaterNum;
2257 0 : auto *thisMaterial = new MaterialChild;
2258 0 : state.dataMaterial->Material(MaterNum) = thisMaterial;
2259 0 : thisMaterial->group = Group::BlindEquivalentLayer;
2260 :
2261 0 : thisMaterial->Name = MaterialNames(1);
2262 0 : thisMaterial->Roughness = SurfaceRoughness::Rough;
2263 0 : thisMaterial->ROnly = true;
2264 :
2265 0 : if (Util::SameString(MaterialNames(2), "Horizontal")) {
2266 0 : thisMaterial->SlatOrientation = DataWindowEquivalentLayer::Orientation::Horizontal;
2267 0 : } else if (Util::SameString(MaterialNames(2), "Vertical")) {
2268 0 : thisMaterial->SlatOrientation = DataWindowEquivalentLayer::Orientation::Vertical;
2269 : }
2270 0 : thisMaterial->SlatWidth = MaterialProps(1);
2271 0 : thisMaterial->SlatSeparation = MaterialProps(2);
2272 0 : thisMaterial->SlatCrown = MaterialProps(3);
2273 0 : thisMaterial->SlatAngle = MaterialProps(4);
2274 :
2275 0 : thisMaterial->TausFrontBeamDiff = MaterialProps(5);
2276 0 : thisMaterial->TausBackBeamDiff = MaterialProps(6);
2277 0 : thisMaterial->ReflFrontBeamDiff = MaterialProps(7);
2278 0 : thisMaterial->ReflBackBeamDiff = MaterialProps(8);
2279 :
2280 0 : if (!ipsc->lNumericFieldBlanks(9) && !ipsc->lNumericFieldBlanks(10) && !ipsc->lNumericFieldBlanks(11) && !ipsc->lNumericFieldBlanks(12)) {
2281 0 : thisMaterial->TausFrontBeamDiffVis = MaterialProps(9);
2282 0 : thisMaterial->TausBackBeamDiffVis = MaterialProps(10);
2283 0 : thisMaterial->ReflFrontBeamDiffVis = MaterialProps(11);
2284 0 : thisMaterial->ReflBackBeamDiffVis = MaterialProps(12);
2285 : }
2286 0 : if (!ipsc->lNumericFieldBlanks(13) && !ipsc->lNumericFieldBlanks(14) && !ipsc->lNumericFieldBlanks(15)) {
2287 0 : thisMaterial->TausDiffDiff = MaterialProps(13);
2288 0 : thisMaterial->ReflFrontDiffDiff = MaterialProps(14);
2289 0 : thisMaterial->ReflBackDiffDiff = MaterialProps(15);
2290 : }
2291 0 : if (!ipsc->lNumericFieldBlanks(16) && !ipsc->lNumericFieldBlanks(17) && !ipsc->lNumericFieldBlanks(18)) {
2292 0 : thisMaterial->TausDiffDiffVis = MaterialProps(13);
2293 0 : thisMaterial->ReflFrontDiffDiffVis = MaterialProps(14);
2294 0 : thisMaterial->ReflBackDiffDiffVis = MaterialProps(15);
2295 : }
2296 0 : if (!ipsc->lNumericFieldBlanks(19)) {
2297 0 : thisMaterial->TausThermal = MaterialProps(19);
2298 : }
2299 0 : if (!ipsc->lNumericFieldBlanks(20)) {
2300 0 : thisMaterial->EmissThermalFront = MaterialProps(20);
2301 : }
2302 0 : if (!ipsc->lNumericFieldBlanks(21)) {
2303 0 : thisMaterial->EmissThermalBack = MaterialProps(21);
2304 : }
2305 : // Assumes thermal emissivity is the same as thermal absorptance
2306 0 : thisMaterial->AbsorpThermalFront = thisMaterial->EmissThermalFront;
2307 0 : thisMaterial->AbsorpThermalBack = thisMaterial->EmissThermalBack;
2308 0 : thisMaterial->TransThermal = thisMaterial->TausThermal;
2309 :
2310 : // By default all blinds have fixed slat angle,
2311 : // they are used with window shading controls that adjust slat angles like
2312 : // MaximizeSolar or BlockBeamSolar
2313 0 : thisMaterial->slatAngleType = SlatAngleType::FixedSlatAngle;
2314 0 : if (!ipsc->lAlphaFieldBlanks(3)) {
2315 0 : thisMaterial->slatAngleType = static_cast<SlatAngleType>(getEnumValue(slatAngleTypeNamesUC, Util::makeUPPER(MaterialNames(3))));
2316 : }
2317 0 : if (thisMaterial->SlatWidth < thisMaterial->SlatSeparation) {
2318 0 : ShowWarningError(state, format("{}=\"{}\", Slat Seperation/Width", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2319 0 : ShowContinueError(state,
2320 0 : format("{} [{:.2R}] is less than {} [{:.2R}].",
2321 0 : ipsc->cNumericFieldNames(1),
2322 0 : thisMaterial->SlatWidth,
2323 0 : ipsc->cNumericFieldNames(2),
2324 0 : thisMaterial->SlatSeparation));
2325 0 : ShowContinueError(state, "This will allow direct beam to be transmitted when Slat angle = 0.");
2326 : }
2327 0 : if (thisMaterial->SlatSeparation < 0.001) {
2328 0 : ShowWarningError(state, format("{}=\"{}\", Slat Seperation", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2329 0 : ShowContinueError(state, format("{} [{:.2R}]. Slate spacing must be > 0.0", ipsc->cNumericFieldNames(2), thisMaterial->SlatSeparation));
2330 0 : ShowContinueError(state,
2331 : "...Setting slate spacing to default value of 0.025 m and "
2332 : "simulation continues.");
2333 0 : thisMaterial->SlatSeparation = 0.025;
2334 : }
2335 0 : if (thisMaterial->SlatWidth < 0.001 || thisMaterial->SlatWidth >= 2.0 * thisMaterial->SlatSeparation) {
2336 0 : ShowWarningError(state, format("{}=\"{}\", Slat Width", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2337 0 : ShowContinueError(
2338 0 : state, format("{} [{:.2R}]. Slat width range is 0 < Width <= 2*Spacing", ipsc->cNumericFieldNames(1), thisMaterial->SlatWidth));
2339 0 : ShowContinueError(state, "...Setting slate width equal to slate spacing and simulation continues.");
2340 0 : thisMaterial->SlatWidth = thisMaterial->SlatSeparation;
2341 : }
2342 0 : if (thisMaterial->SlatCrown < 0.0 || thisMaterial->SlatCrown >= 0.5 * thisMaterial->SlatWidth) {
2343 0 : ShowWarningError(state, format("{}=\"{}\", Slat Crown", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2344 0 : ShowContinueError(
2345 0 : state, format("{} [{:.2R}]. Slat crwon range is 0 <= crown < 0.5*Width", ipsc->cNumericFieldNames(3), thisMaterial->SlatCrown));
2346 0 : ShowContinueError(state, "...Setting slate crown to 0.0 and simulation continues.");
2347 0 : thisMaterial->SlatCrown = 0.0;
2348 : }
2349 0 : if (thisMaterial->SlatAngle < -90.0 || thisMaterial->SlatAngle > 90.0) {
2350 0 : ShowWarningError(state, format("{}=\"{}\", Slat Angle", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2351 0 : ShowContinueError(state,
2352 0 : format("{} [{:.2R}]. Slat angle range is -90.0 <= Angle < 90.0", ipsc->cNumericFieldNames(4), thisMaterial->SlatAngle));
2353 0 : ShowContinueError(state, "...Setting slate angle to 0.0 and simulation continues.");
2354 0 : thisMaterial->SlatAngle = 0.0;
2355 : }
2356 :
2357 0 : if (!Util::SameString(MaterialNames(2), "Horizontal") && !Util::SameString(MaterialNames(2), "Vertical")) {
2358 0 : ErrorsFound = true;
2359 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2360 0 : ShowContinueError(state, format("{}=\"{}\", must be Horizontal or Vertical.", ipsc->cAlphaFieldNames(2), MaterialNames(2)));
2361 : }
2362 :
2363 0 : if ((MaterialProps(5) + MaterialProps(7) >= 1.0)) {
2364 0 : ErrorsFound = true;
2365 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2366 0 : ShowContinueError(state, format("{} + {} not < 1.0", ipsc->cNumericFieldNames(5), ipsc->cNumericFieldNames(7)));
2367 : }
2368 0 : if ((MaterialProps(6) + MaterialProps(8) >= 1.0)) {
2369 0 : ErrorsFound = true;
2370 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2371 0 : ShowContinueError(state, format("{} + {} not < 1.0", ipsc->cNumericFieldNames(6), ipsc->cNumericFieldNames(8)));
2372 : }
2373 0 : if ((MaterialProps(9) + MaterialProps(11) >= 1.0)) {
2374 0 : ErrorsFound = true;
2375 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2376 0 : ShowContinueError(state, format("{} + {} not < 1.0", ipsc->cNumericFieldNames(9), ipsc->cNumericFieldNames(11)));
2377 : }
2378 0 : if ((MaterialProps(10) + MaterialProps(12) >= 1.0)) {
2379 0 : ErrorsFound = true;
2380 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2381 0 : ShowContinueError(state, format("{} + {} not < 1.0", ipsc->cNumericFieldNames(10), ipsc->cNumericFieldNames(12)));
2382 : }
2383 :
2384 : } // TotBlindsEQL loop
2385 :
2386 : // EcoRoof Materials
2387 : // PSU 2006
2388 796 : state.dataHeatBalMgr->CurrentModuleObject = "Material:RoofVegetation";
2389 808 : for (Loop = 1; Loop <= EcoRoofMat; ++Loop) {
2390 : // Call Input Get Routine to retrieve material data from ecoroof
2391 :
2392 36 : ip->getObjectItem(state,
2393 12 : state.dataHeatBalMgr->CurrentModuleObject,
2394 : Loop,
2395 : MaterialNames,
2396 : MaterialNumAlpha,
2397 : MaterialProps,
2398 : MaterialNumProp,
2399 : IOStat,
2400 12 : ipsc->lNumericFieldBlanks,
2401 12 : ipsc->lAlphaFieldBlanks,
2402 12 : ipsc->cAlphaFieldNames,
2403 12 : ipsc->cNumericFieldNames);
2404 24 : if (GlobalNames::VerifyUniqueInterObjectName(state,
2405 12 : state.dataHeatBalMgr->UniqueMaterialNames,
2406 12 : MaterialNames(1),
2407 12 : state.dataHeatBalMgr->CurrentModuleObject,
2408 12 : ipsc->cAlphaFieldNames(1),
2409 : ErrorsFound)) {
2410 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
2411 0 : continue;
2412 : }
2413 :
2414 : // this part is similar to the regular material
2415 : // Load the material derived type from the input data.
2416 12 : ++MaterNum;
2417 12 : auto *thisMaterial = new MaterialChild;
2418 12 : state.dataMaterial->Material(MaterNum) = thisMaterial;
2419 12 : thisMaterial->group = Group::EcoRoof;
2420 :
2421 : // this part is new for Ecoroof properties,
2422 : // especially for the Plant Layer of the ecoroof
2423 12 : thisMaterial->HeightOfPlants = MaterialProps(1);
2424 12 : thisMaterial->LAI = MaterialProps(2);
2425 12 : thisMaterial->Lreflectivity = MaterialProps(3); // Albedo
2426 12 : thisMaterial->LEmissitivity = MaterialProps(4);
2427 12 : thisMaterial->RStomata = MaterialProps(5);
2428 :
2429 12 : thisMaterial->Name = MaterialNames(1);
2430 : // need to treat the A2 with is just the name of the soil(it is
2431 : // not important)
2432 12 : thisMaterial->Roughness = static_cast<SurfaceRoughness>(getEnumValue(surfaceRoughnessNamesUC, Util::makeUPPER(MaterialNames(3))));
2433 12 : if (Util::SameString(MaterialNames(4), "Simple")) {
2434 6 : thisMaterial->EcoRoofCalculationMethod = 1;
2435 6 : } else if (Util::SameString(MaterialNames(4), "Advanced") || ipsc->lAlphaFieldBlanks(4)) {
2436 6 : thisMaterial->EcoRoofCalculationMethod = 2;
2437 : } else {
2438 0 : ShowSevereError(state, format("{}=\"{}\", Illegal value", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2439 0 : ShowContinueError(state, format("{}=\"{}\".", ipsc->cAlphaFieldNames(4), MaterialNames(4)));
2440 0 : ShowContinueError(state, "...Valid values are \"Simple\" or \"Advanced\".");
2441 0 : ErrorsFound = true;
2442 : }
2443 :
2444 12 : thisMaterial->Thickness = MaterialProps(6);
2445 12 : thisMaterial->Conductivity = MaterialProps(7);
2446 12 : thisMaterial->Density = MaterialProps(8);
2447 12 : thisMaterial->SpecHeat = MaterialProps(9);
2448 12 : thisMaterial->AbsorpThermal = MaterialProps(10); // emissivity
2449 12 : thisMaterial->AbsorpSolar = MaterialProps(11); // (1 - Albedo)
2450 12 : thisMaterial->AbsorpVisible = MaterialProps(12);
2451 12 : thisMaterial->Porosity = MaterialProps(13);
2452 12 : thisMaterial->MinMoisture = MaterialProps(14);
2453 12 : thisMaterial->InitMoisture = MaterialProps(15);
2454 :
2455 12 : if (thisMaterial->Conductivity > 0.0) {
2456 12 : state.dataHeatBal->NominalR(MaterNum) = thisMaterial->Thickness / thisMaterial->Conductivity;
2457 12 : thisMaterial->Resistance = state.dataHeatBal->NominalR(MaterNum);
2458 : } else {
2459 0 : ShowSevereError(state, format("{}=\"{}\" is not defined correctly.", state.dataHeatBalMgr->CurrentModuleObject, ipsc->cAlphaArgs(1)));
2460 0 : ShowContinueError(state, format("{} is <=0.", ipsc->cNumericFieldNames(7)));
2461 0 : ErrorsFound = true;
2462 : }
2463 :
2464 12 : if (thisMaterial->InitMoisture > thisMaterial->Porosity) {
2465 0 : ShowWarningError(state, format("{}=\"{}\", Illegal value combination.", state.dataHeatBalMgr->CurrentModuleObject, MaterialNames(1)));
2466 0 : ShowContinueError(state,
2467 0 : format("{} is greater than {}. It must be less or equal.", ipsc->cNumericFieldNames(15), ipsc->cNumericFieldNames(13)));
2468 0 : ShowContinueError(state, format("{} = {:.3T}.", ipsc->cNumericFieldNames(13), thisMaterial->Porosity));
2469 0 : ShowContinueError(state, format("{} = {:.3T}.", ipsc->cNumericFieldNames(15), thisMaterial->InitMoisture));
2470 0 : ShowContinueError(
2471 0 : state, format("{} is reset to the maximum (saturation) value = {:.3T}.", ipsc->cNumericFieldNames(15), thisMaterial->Porosity));
2472 0 : ShowContinueError(state, "Simulation continues.");
2473 0 : thisMaterial->InitMoisture = thisMaterial->Porosity;
2474 : }
2475 : }
2476 :
2477 : // Thermochromic glazing group
2478 : // get the number of WindowMaterial:GlazingGroup:Thermochromic objects in the idf file
2479 796 : state.dataHeatBalMgr->CurrentModuleObject = "WindowMaterial:GlazingGroup:Thermochromic";
2480 796 : state.dataHeatBal->TotTCGlazings = ip->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject);
2481 796 : if (state.dataHeatBal->TotTCGlazings >= 1) {
2482 : // Read TC glazings
2483 1 : state.dataHeatBal->TCGlazings.allocate(state.dataHeatBal->TotTCGlazings);
2484 :
2485 2 : for (Loop = 1; Loop <= state.dataHeatBal->TotTCGlazings; ++Loop) {
2486 : // Get each TCGlazings from the input processor
2487 2 : ip->getObjectItem(state,
2488 1 : state.dataHeatBalMgr->CurrentModuleObject,
2489 : Loop,
2490 1 : ipsc->cAlphaArgs,
2491 : MaterialNumAlpha,
2492 1 : ipsc->rNumericArgs,
2493 : MaterialNumProp,
2494 : IOStat,
2495 1 : ipsc->lNumericFieldBlanks,
2496 1 : ipsc->lAlphaFieldBlanks,
2497 1 : ipsc->cAlphaFieldNames,
2498 1 : ipsc->cNumericFieldNames);
2499 :
2500 1 : if (Util::IsNameEmpty(state, ipsc->cAlphaArgs(1), state.dataHeatBalMgr->CurrentModuleObject, ErrorsFound)) {
2501 0 : ShowContinueError(state, "...All Thermochromic Glazing names must be unique regardless of subtype.");
2502 0 : continue;
2503 : }
2504 :
2505 1 : if (MaterialNumProp + 1 != MaterialNumAlpha) {
2506 0 : ShowSevereError(state, format("{}=\"{}\" is not defined correctly.", state.dataHeatBalMgr->CurrentModuleObject, ipsc->cAlphaArgs(1)));
2507 0 : ShowContinueError(state,
2508 0 : format("Check number of {} compared to number of {}", ipsc->cAlphaFieldNames(2), ipsc->cNumericFieldNames(1)));
2509 0 : ErrorsFound = true;
2510 0 : continue;
2511 : }
2512 :
2513 : // Allocate arrays
2514 1 : state.dataHeatBal->TCGlazings(Loop).SpecTemp.allocate(MaterialNumProp);
2515 1 : state.dataHeatBal->TCGlazings(Loop).LayerName.allocate(MaterialNumProp);
2516 1 : state.dataHeatBal->TCGlazings(Loop).LayerPoint.allocate(MaterialNumProp);
2517 1 : state.dataHeatBal->TCGlazings(Loop).SpecTemp = 0.0;
2518 1 : state.dataHeatBal->TCGlazings(Loop).LayerName = "";
2519 1 : state.dataHeatBal->TCGlazings(Loop).LayerPoint = 0;
2520 :
2521 1 : state.dataHeatBal->TCGlazings(Loop).Name = ipsc->cAlphaArgs(1);
2522 1 : state.dataHeatBal->TCGlazings(Loop).NumGlzMat = MaterialNumProp;
2523 :
2524 20 : for (iTC = 1; iTC <= MaterialNumProp; ++iTC) {
2525 19 : state.dataHeatBal->TCGlazings(Loop).SpecTemp(iTC) = ipsc->rNumericArgs(iTC);
2526 19 : state.dataHeatBal->TCGlazings(Loop).LayerName(iTC) = ipsc->cAlphaArgs(1 + iTC);
2527 :
2528 : // Find this glazing material in the material list
2529 19 : iMat = Util::FindItemInPtrList(ipsc->cAlphaArgs(1 + iTC), state.dataMaterial->Material);
2530 19 : if (iMat != 0) {
2531 : // TC glazing
2532 19 : auto *thisMaterial = dynamic_cast<MaterialChild *>(state.dataMaterial->Material(iMat));
2533 19 : assert(thisMaterial != nullptr);
2534 19 : thisMaterial->SpecTemp = ipsc->rNumericArgs(iTC);
2535 19 : thisMaterial->TCParent = Loop;
2536 19 : state.dataHeatBal->TCGlazings(Loop).LayerPoint(iTC) = iMat;
2537 :
2538 : // test that named material is of the right type
2539 19 : if (thisMaterial->group != Group::WindowGlass) {
2540 0 : ShowSevereError(
2541 0 : state, format("{}=\"{}\" is not defined correctly.", state.dataHeatBalMgr->CurrentModuleObject, ipsc->cAlphaArgs(1)));
2542 0 : ShowContinueError(state, format("Material named: {} is not a window glazing ", ipsc->cAlphaArgs(1 + iTC)));
2543 0 : ErrorsFound = true;
2544 : }
2545 :
2546 : } else { // thow error because not found
2547 0 : ShowSevereError(state,
2548 0 : format("{}=\"{}\" is not defined correctly.", state.dataHeatBalMgr->CurrentModuleObject, ipsc->cAlphaArgs(1)));
2549 0 : ShowContinueError(state, format("Material named: {} was not found ", ipsc->cAlphaArgs(1 + iTC)));
2550 0 : ErrorsFound = true;
2551 : }
2552 : }
2553 : }
2554 : }
2555 796 : auto &cCurrentModuleObject = ipsc->cCurrentModuleObject;
2556 796 : cCurrentModuleObject = "WindowMaterial:SimpleGlazingSystem";
2557 904 : for (Loop = 1; Loop <= state.dataHeatBal->TotSimpleWindow; ++Loop) {
2558 :
2559 216 : ip->getObjectItem(state,
2560 : cCurrentModuleObject,
2561 : Loop,
2562 108 : ipsc->cAlphaArgs,
2563 : MaterialNumAlpha,
2564 108 : ipsc->rNumericArgs,
2565 : MaterialNumProp,
2566 : IOStat,
2567 108 : ipsc->lNumericFieldBlanks,
2568 108 : ipsc->lAlphaFieldBlanks,
2569 108 : ipsc->cAlphaFieldNames,
2570 108 : ipsc->cNumericFieldNames);
2571 216 : if (GlobalNames::VerifyUniqueInterObjectName(state,
2572 108 : state.dataHeatBalMgr->UniqueMaterialNames,
2573 108 : ipsc->cAlphaArgs(1),
2574 108 : state.dataHeatBalMgr->CurrentModuleObject,
2575 108 : ipsc->cAlphaFieldNames(1),
2576 : ErrorsFound)) {
2577 0 : ShowContinueError(state, "...All Material names must be unique regardless of subtype.");
2578 0 : continue;
2579 : }
2580 :
2581 108 : ++MaterNum;
2582 108 : auto *thisMaterial = new MaterialChild;
2583 108 : state.dataMaterial->Material(MaterNum) = thisMaterial;
2584 108 : thisMaterial->group = Group::WindowSimpleGlazing;
2585 108 : thisMaterial->Name = ipsc->cAlphaArgs(1);
2586 108 : thisMaterial->SimpleWindowUfactor = ipsc->rNumericArgs(1);
2587 108 : thisMaterial->SimpleWindowSHGC = ipsc->rNumericArgs(2);
2588 108 : if (!ipsc->lNumericFieldBlanks(3)) {
2589 48 : thisMaterial->SimpleWindowVisTran = ipsc->rNumericArgs(3);
2590 48 : thisMaterial->SimpleWindowVTinputByUser = true;
2591 : }
2592 :
2593 108 : HeatBalanceManager::SetupSimpleWindowGlazingSystem(state, MaterNum);
2594 : }
2595 :
2596 : // Simon: Place to load materials for complex fenestrations
2597 796 : if ((state.dataMaterial->TotComplexShades > 0) || (state.dataHeatBal->TotComplexGaps > 0)) {
2598 10 : HeatBalanceManager::SetupComplexFenestrationMaterialInput(state, MaterNum, ErrorsFound);
2599 10 : if (ErrorsFound) {
2600 0 : ShowSevereError(state, "Errors found in processing complex fenestration material input");
2601 : }
2602 : }
2603 796 : ScanForReports(state, "Constructions", state.dataHeatBalMgr->DoReport, "Materials");
2604 :
2605 796 : if (state.dataHeatBalMgr->DoReport) {
2606 :
2607 14 : print(state.files.eio,
2608 : "! <Material Details>,Material Name,ThermalResistance {{m2-K/w}},Roughness,Thickness {{m}},Conductivity "
2609 : "{{w/m-K}},Density {{kg/m3}},Specific Heat "
2610 : "{{J/kg-K}},Absorptance:Thermal,Absorptance:Solar,Absorptance:Visible\n");
2611 :
2612 14 : print(state.files.eio, "! <Material:Air>,Material Name,ThermalResistance {{m2-K/w}}\n");
2613 :
2614 : // Formats
2615 14 : constexpr std::string_view Format_701(" Material Details,{},{:.4R},{},{:.4R},{:.3R},{:.3R},{:.3R},{:.4R},{:.4R},{:.4R}\n");
2616 14 : constexpr std::string_view Format_702(" Material:Air,{},{:.4R}\n");
2617 :
2618 279 : for (auto const *mat : state.dataMaterial->Material) {
2619 :
2620 265 : switch (mat->group) {
2621 11 : case Group::Air: {
2622 11 : print(state.files.eio, Format_702, mat->Name, mat->Resistance);
2623 11 : } break;
2624 254 : default: {
2625 254 : print(state.files.eio,
2626 : Format_701,
2627 254 : mat->Name,
2628 254 : mat->Resistance,
2629 254 : surfaceRoughnessNames[(int)mat->Roughness],
2630 254 : mat->Thickness,
2631 254 : mat->Conductivity,
2632 254 : mat->Density,
2633 254 : mat->SpecHeat,
2634 254 : mat->AbsorpThermal,
2635 254 : mat->AbsorpSolar,
2636 254 : mat->AbsorpVisible);
2637 254 : } break;
2638 : }
2639 14 : }
2640 : }
2641 :
2642 : // FORMATS.
2643 :
2644 796 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // setup surface property EMS actuators
2645 :
2646 2198 : for (auto *mat : state.dataMaterial->Material) {
2647 2125 : if (mat->group != Group::Regular) continue;
2648 :
2649 1793 : auto *matReg = dynamic_cast<MaterialChild *>(mat);
2650 1793 : assert(matReg != nullptr);
2651 1793 : SetupEMSActuator(state,
2652 : "Material",
2653 : matReg->Name,
2654 : "Surface Property Solar Absorptance",
2655 : "[ ]",
2656 1793 : matReg->AbsorpSolarEMSOverrideOn,
2657 1793 : matReg->AbsorpSolarEMSOverride);
2658 1793 : SetupEMSActuator(state,
2659 : "Material",
2660 : matReg->Name,
2661 : "Surface Property Thermal Absorptance",
2662 : "[ ]",
2663 1793 : matReg->AbsorpThermalEMSOverrideOn,
2664 1793 : matReg->AbsorpThermalEMSOverride);
2665 1793 : SetupEMSActuator(state,
2666 : "Material",
2667 : matReg->Name,
2668 : "Surface Property Visible Absorptance",
2669 : "[ ]",
2670 1793 : matReg->AbsorpVisibleEMSOverrideOn,
2671 1793 : matReg->AbsorpVisibleEMSOverride);
2672 73 : }
2673 : }
2674 :
2675 : // try assigning phase change material properties for each material, won't do anything for non pcm surfaces
2676 14714 : for (auto *mBase : state.dataMaterial->Material) {
2677 13918 : if (mBase->group == Material::Group::Screen || mBase->group == Material::Group::WindowGas ||
2678 13103 : mBase->group == Material::Group::WindowGasMixture || mBase->group == Material::Group::GapEquivalentLayer)
2679 839 : continue;
2680 :
2681 13079 : auto *m = dynamic_cast<MaterialChild *>(mBase);
2682 13079 : assert(m != nullptr);
2683 13079 : m->phaseChange = HysteresisPhaseChange::HysteresisPhaseChange::factory(state, m->Name);
2684 796 : }
2685 :
2686 796 : GetVariableAbsorptanceInput(state, ErrorsFound); // Read variable thermal and solar absorptance add-on data
2687 796 : }
2688 :
2689 796 : void GetVariableAbsorptanceInput(EnergyPlusData &state, bool &errorsFound)
2690 : {
2691 : int IOStat; // IO Status when calling get input subroutine
2692 : int numAlphas;
2693 : int numNumbers;
2694 796 : Array1D_string alphas(7); // character string data
2695 796 : Array1D<Real64> numbers(1); // numeric data
2696 796 : std::string_view cCurrentModuleObject{"MaterialProperty:VariableAbsorptance"};
2697 :
2698 796 : auto &ip = state.dataInputProcessing->inputProcessor;
2699 796 : auto &ipsc = state.dataIPShortCut;
2700 :
2701 796 : int numVariAbs = ip->getNumObjectsFound(state, cCurrentModuleObject);
2702 796 : state.dataHeatBal->AnyVariableAbsorptance = (numVariAbs > 0);
2703 797 : for (int i = 1; i <= numVariAbs; ++i) {
2704 : // Call Input Get routine to retrieve material data
2705 2 : ip->getObjectItem(state,
2706 : cCurrentModuleObject,
2707 : i,
2708 : alphas,
2709 : numAlphas,
2710 : numbers,
2711 : numNumbers,
2712 : IOStat,
2713 1 : ipsc->lNumericFieldBlanks,
2714 1 : ipsc->lAlphaFieldBlanks,
2715 1 : ipsc->cAlphaFieldNames,
2716 1 : ipsc->cNumericFieldNames);
2717 :
2718 : // Load the material derived type from the input data.
2719 1 : int MaterNum = Util::FindItemInPtrList(alphas(2), state.dataMaterial->Material);
2720 1 : if (MaterNum == 0) {
2721 0 : ShowSevereError(
2722 : state,
2723 0 : format(
2724 0 : "{}: invalid {} entered={}, must match to a valid Material name.", cCurrentModuleObject, ipsc->cAlphaFieldNames(2), alphas(2)));
2725 0 : errorsFound = true;
2726 0 : return;
2727 : }
2728 1 : auto *thisMaterial = dynamic_cast<MaterialChild *>(state.dataMaterial->Material(MaterNum));
2729 1 : assert(thisMaterial != nullptr);
2730 :
2731 1 : if (thisMaterial->group != Group::Regular) {
2732 0 : ShowSevereError(
2733 : state,
2734 0 : format("{}: Reference Material is not appropriate type for Thermal/Solar Absorptance properties, material={}, must have regular "
2735 : "properties (Thermal/Solar Absorptance)",
2736 : cCurrentModuleObject,
2737 0 : thisMaterial->Name));
2738 0 : errorsFound = true;
2739 0 : return;
2740 : }
2741 :
2742 1 : thisMaterial->absorpVarCtrlSignal = VariableAbsCtrlSignal::SurfaceTemperature; // default value
2743 1 : thisMaterial->absorpVarCtrlSignal =
2744 1 : static_cast<VariableAbsCtrlSignal>(getEnumValue(variableAbsCtrlSignalNamesUC, Util::makeUPPER(alphas(3))));
2745 : // init to 0 as GetScheduleIndex returns 0 for not-found schedule
2746 1 : thisMaterial->absorpThermalVarFuncIdx = Curve::GetCurveIndex(state, alphas(4));
2747 1 : thisMaterial->absorpThermalVarSchedIdx = ScheduleManager::GetScheduleIndex(state, alphas(5));
2748 1 : thisMaterial->absorpSolarVarFuncIdx = Curve::GetCurveIndex(state, alphas(6));
2749 1 : thisMaterial->absorpSolarVarSchedIdx = ScheduleManager::GetScheduleIndex(state, alphas(7));
2750 1 : if (thisMaterial->absorpVarCtrlSignal == VariableAbsCtrlSignal::Scheduled) {
2751 0 : if ((thisMaterial->absorpThermalVarSchedIdx == 0) && (thisMaterial->absorpSolarVarSchedIdx == 0)) {
2752 0 : ShowSevereError(
2753 : state,
2754 0 : format("{}: Control signal \"Scheduled\" is chosen but both thermal and solar absorptance schedules are undefined, for object {}",
2755 : cCurrentModuleObject,
2756 : alphas(1)));
2757 0 : errorsFound = true;
2758 0 : return;
2759 : }
2760 0 : if ((thisMaterial->absorpThermalVarFuncIdx > 0) || (thisMaterial->absorpSolarVarFuncIdx > 0)) {
2761 0 : ShowWarningError(state,
2762 0 : format("{}: Control signal \"Scheduled\" is chosen. Thermal or solar absorptance function name is going to be "
2763 : "ignored, for object {}",
2764 : cCurrentModuleObject,
2765 : alphas(1)));
2766 0 : errorsFound = true;
2767 0 : return;
2768 : }
2769 : } else { // controlled by performance table or curve
2770 1 : if ((thisMaterial->absorpThermalVarFuncIdx == 0) && (thisMaterial->absorpSolarVarFuncIdx == 0)) {
2771 0 : ShowSevereError(state,
2772 0 : format("{}: Non-schedule control signal is chosen but both thermal and solar absorptance table or curve are "
2773 : "undefined, for object {}",
2774 : cCurrentModuleObject,
2775 : alphas(1)));
2776 0 : errorsFound = true;
2777 0 : return;
2778 : }
2779 1 : if ((thisMaterial->absorpThermalVarSchedIdx > 0) || (thisMaterial->absorpSolarVarSchedIdx > 0)) {
2780 0 : ShowWarningError(state,
2781 0 : format("{}: Non-schedule control signal is chosen. Thermal or solar absorptance schedule name is going to be "
2782 : "ignored, for object {}",
2783 : cCurrentModuleObject,
2784 : alphas(1)));
2785 0 : errorsFound = true;
2786 0 : return;
2787 : }
2788 : }
2789 : }
2790 796 : }
2791 :
2792 3386 : void CalcScreenTransmittance(EnergyPlusData &state,
2793 : MaterialScreen const *screen,
2794 : Real64 phi, // Sun altitude relative to surface outward normal (radians, 0 to Pi)
2795 : Real64 theta, // Optional sun azimuth relative to surface outward normal (radians, 0 to Pi)
2796 : ScreenBmTransAbsRef &tar)
2797 : {
2798 :
2799 : // FUNCTION INFORMATION:
2800 : // AUTHOR Richard Raustad
2801 : // DATE WRITTEN May 2006
2802 : // MODIFIED na
2803 : // RE-ENGINEERED na
2804 :
2805 : // PURPOSE OF THIS FUNCTION:
2806 : // Calculate transmittance of window screen given azimuth and altitude angle
2807 : // of sun and surface orientation.
2808 :
2809 : // METHODOLOGY EMPLOYED:
2810 : // Window screen solar beam transmittance varies as the sun moves across the sky
2811 : // due to the geometry of the screen material and the angle of incidence
2812 : // of the solar beam. Azimuth and altitude angle are calculated with respect
2813 : // to the surface outward normal. Solar beam reflectance and absorptance are also
2814 : // accounted for.
2815 :
2816 3386 : Real64 constexpr Small(1.E-9); // Small Number used to approximate zero
2817 :
2818 : Real64 Tdirect; // Beam solar transmitted through screen (dependent on sun angle)
2819 : Real64 Tscattered; // Beam solar reflected through screen (dependent on sun angle)
2820 : Real64 TscatteredVis; // Visible beam solar reflected through screen (dependent on sun angle)
2821 : Real64 Tscattermax; // Maximum solar beam scattered transmittance
2822 : Real64 TscattermaxVis; // Maximum visible beam scattered transmittance
2823 : Real64 ExponentInterior; // Exponent used in scattered transmittance calculation
2824 : // when Delta < DeltaMax (0,0 to peak)
2825 : Real64 ExponentExterior; // Exponent used in scattered transmittance calculation
2826 : // when Delta > DeltaMax (peak to max)
2827 :
2828 3386 : assert(phi >= 0.0 && phi <= Constant::Pi);
2829 3386 : assert(theta >= 0.0 && theta <= Constant::Pi);
2830 :
2831 3386 : Real64 sinPhi = std::sin(phi);
2832 3386 : Real64 cosPhi = std::cos(phi);
2833 3386 : Real64 tanPhi = sinPhi / cosPhi;
2834 3386 : Real64 sinTheta = std::sin(theta);
2835 3386 : Real64 cosTheta = std::cos(theta);
2836 3386 : Real64 tanTheta = sinTheta / cosTheta;
2837 :
2838 3386 : bool sunInFront = (phi < Constant::PiOvr2) && (theta < Constant::PiOvr2); // Sun is in front of screen
2839 :
2840 : // ratio of screen material diameter to screen material spacing
2841 3386 : Real64 Gamma = screen->diameterToSpacingRatio;
2842 :
2843 : // ************************************************************************************************
2844 : // * calculate transmittance of totally absorbing screen material (beam passing through open area)*
2845 : // ************************************************************************************************
2846 :
2847 : // Now we need to normalize phi and theta to the 0 to Pi/2 range using reflection.
2848 3386 : if (phi > Constant::PiOvr2) phi = Constant::Pi - phi;
2849 3386 : if (theta > Constant::PiOvr2) theta = Constant::Pi - theta;
2850 :
2851 : // calculate compliment of relative solar azimuth
2852 3386 : Real64 Beta = Constant::PiOvr2 - theta;
2853 :
2854 : // Catch all divide by zero instances
2855 : Real64 TransYDir;
2856 : Real64 TransXDir;
2857 3386 : if (Beta > Small && std::abs(phi - Constant::PiOvr2) > Small) {
2858 3240 : Real64 AlphaDblPrime = std::atan(tanPhi / cosTheta);
2859 3240 : TransYDir = 1.0 - Gamma * (std::cos(AlphaDblPrime) + std::sin(AlphaDblPrime) * tanPhi * std::sqrt(1.0 + pow_2(1.0 / std::tan(Beta))));
2860 3240 : TransYDir = max(0.0, TransYDir);
2861 : } else {
2862 146 : TransYDir = 0.0;
2863 : }
2864 :
2865 3386 : Real64 COSMu = std::sqrt(pow_2(cosPhi) * pow_2(cosTheta) + pow_2(sinPhi));
2866 3386 : if (COSMu <= Small) {
2867 4 : TransXDir = 1.0 - Gamma;
2868 : } else {
2869 3382 : Real64 Epsilon = std::acos(cosPhi * cosTheta / COSMu);
2870 3382 : Real64 Eta = Constant::PiOvr2 - Epsilon;
2871 3382 : if (std::cos(Epsilon) != 0.0 && Eta != 0.0) {
2872 3282 : Real64 MuPrime = std::atan(std::tan(std::acos(COSMu)) / std::cos(Epsilon));
2873 3282 : TransXDir =
2874 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))));
2875 3282 : TransXDir = max(0.0, TransXDir);
2876 3282 : } else {
2877 100 : TransXDir = 0.0;
2878 : }
2879 : }
2880 3386 : Tdirect = max(0.0, TransXDir * TransYDir);
2881 :
2882 : // *******************************************************************************
2883 : // * calculate transmittance of scattered beam due to reflecting screen material *
2884 : // *******************************************************************************
2885 :
2886 3386 : Real64 ReflCyl = screen->CylinderRef;
2887 3386 : Real64 ReflCylVis = screen->CylinderRefVis;
2888 :
2889 3386 : if ((Constant::PiOvr2 - theta) < Small || (Constant::PiOvr2 - phi) < Small) {
2890 146 : Tscattered = 0.0;
2891 146 : TscatteredVis = 0.0;
2892 : } else {
2893 : // DeltaMax and Delta are in degrees
2894 3240 : Real64 DeltaMax = 89.7 - (10.0 * Gamma / 0.16);
2895 3240 : Real64 Delta = std::sqrt(pow_2(theta / Constant::DegToRad) + pow_2(phi / Constant::DegToRad));
2896 :
2897 : // Use empirical model to determine maximum (peak) scattering
2898 3240 : Real64 Tscattermax = 0.0229 * Gamma + 0.2971 * ReflCyl - 0.03624 * pow_2(Gamma) + 0.04763 * pow_2(ReflCyl) - 0.44416 * Gamma * ReflCyl;
2899 : Real64 TscattermaxVis =
2900 3240 : 0.0229 * Gamma + 0.2971 * ReflCylVis - 0.03624 * pow_2(Gamma) + 0.04763 * pow_2(ReflCylVis) - 0.44416 * Gamma * ReflCylVis;
2901 :
2902 : // Vary slope of interior and exterior surface of scattering model
2903 3240 : Real64 ExponentInterior = -pow_2(Delta - DeltaMax) / 600.0;
2904 3240 : Real64 ExponentExterior = -std::pow(std::abs(Delta - DeltaMax), 2.5) / 600.0;
2905 :
2906 : // Determine ratio of scattering at 0,0 incident angle to maximum (peak) scattering
2907 3240 : Real64 PeakToPlateauRatio = 1.0 / (0.2 * (1 - Gamma) * ReflCyl);
2908 3240 : Real64 PeakToPlateauRatioVis = 1.0 / (0.2 * (1 - Gamma) * ReflCylVis);
2909 :
2910 : // Apply offset for plateau and use exterior exponential function to simulate actual scattering as a function of solar angles
2911 3240 : if (Delta > DeltaMax) {
2912 968 : Tscattered = 0.2 * (1.0 - Gamma) * ReflCyl * Tscattermax * (1.0 + (PeakToPlateauRatio - 1.0) * std::exp(ExponentExterior));
2913 968 : TscatteredVis = 0.2 * (1.0 - Gamma) * ReflCylVis * TscattermaxVis * (1.0 + (PeakToPlateauRatioVis - 1.0) * std::exp(ExponentExterior));
2914 : // Trim off offset if solar angle (delta) is greater than maximum (peak) scattering angle
2915 968 : Tscattered -= (0.2 * (1.0 - Gamma) * ReflCyl * Tscattermax) * max(0.0, (Delta - DeltaMax) / (90.0 - DeltaMax));
2916 968 : TscatteredVis -= (0.2 * (1.0 - Gamma) * ReflCylVis * TscattermaxVis) * max(0.0, (Delta - DeltaMax) / (90.0 - DeltaMax));
2917 : } else {
2918 2272 : Tscattered = 0.2 * (1.0 - Gamma) * ReflCyl * Tscattermax * (1.0 + (PeakToPlateauRatio - 1.0) * std::exp(ExponentInterior));
2919 2272 : TscatteredVis = 0.2 * (1.0 - Gamma) * ReflCylVis * TscattermaxVis * (1.0 + (PeakToPlateauRatioVis - 1.0) * std::exp(ExponentInterior));
2920 : }
2921 : }
2922 :
2923 3386 : if (screen->bmRefModel == Material::ScreenBeamReflectanceModel::DoNotModel) {
2924 0 : if (sunInFront) {
2925 0 : tar.BmTrans = Tdirect;
2926 0 : tar.BmTransVis = Tdirect;
2927 0 : tar.BmTransBack = 0.0;
2928 : } else {
2929 0 : tar.BmTrans = 0.0;
2930 0 : tar.BmTransVis = 0.0;
2931 0 : tar.BmTransBack = Tdirect;
2932 : }
2933 0 : Tscattered = 0.0;
2934 0 : TscatteredVis = 0.0;
2935 3386 : } else if (screen->bmRefModel == Material::ScreenBeamReflectanceModel::DirectBeam) {
2936 0 : if (sunInFront) {
2937 0 : tar.BmTrans = Tdirect + Tscattered;
2938 0 : tar.BmTransVis = Tdirect + TscatteredVis;
2939 0 : tar.BmTransBack = 0.0;
2940 : } else {
2941 0 : tar.BmTrans = 0.0;
2942 0 : tar.BmTransVis = 0.0;
2943 0 : tar.BmTransBack = Tdirect + Tscattered;
2944 : }
2945 0 : Tscattered = 0.0;
2946 0 : TscatteredVis = 0.0;
2947 3386 : } else if (screen->bmRefModel == Material::ScreenBeamReflectanceModel::Diffuse) {
2948 3386 : if (sunInFront) {
2949 1296 : tar.BmTrans = Tdirect;
2950 1296 : tar.BmTransVis = Tdirect;
2951 1296 : tar.BmTransBack = 0.0;
2952 : } else {
2953 2090 : tar.BmTrans = 0.0;
2954 2090 : tar.BmTransVis = 0.0;
2955 2090 : tar.BmTransBack = Tdirect;
2956 : }
2957 3386 : Tscattered = max(0.0, Tscattered);
2958 3386 : TscatteredVis = max(0.0, TscatteredVis);
2959 : }
2960 :
2961 3386 : if (sunInFront) {
2962 1296 : tar.DfTrans = Tscattered;
2963 1296 : tar.DfTransVis = TscatteredVis;
2964 1296 : tar.DfTransBack = 0.0;
2965 1296 : tar.RefSolFront = max(0.0, ReflCyl * (1.0 - Tdirect) - Tscattered);
2966 1296 : tar.RefVisFront = max(0.0, ReflCylVis * (1.0 - Tdirect) - TscatteredVis);
2967 1296 : tar.AbsSolFront = max(0.0, (1.0 - Tdirect) * (1.0 - ReflCyl));
2968 1296 : tar.RefSolBack = 0.0;
2969 1296 : tar.RefVisBack = 0.0;
2970 1296 : tar.AbsSolBack = 0.0;
2971 : } else {
2972 2090 : tar.DfTrans = 0.0;
2973 2090 : tar.DfTransVis = 0.0;
2974 2090 : tar.DfTransBack = Tscattered;
2975 2090 : tar.RefSolFront = 0.0;
2976 2090 : tar.RefVisFront = 0.0;
2977 2090 : tar.AbsSolFront = 0.0;
2978 2090 : tar.RefSolBack = max(0.0, ReflCyl * (1.0 - Tdirect) - Tscattered);
2979 2090 : tar.RefVisBack = max(0.0, ReflCylVis * (1.0 - Tdirect) - TscatteredVis);
2980 2090 : tar.AbsSolBack = max(0.0, (1.0 - Tdirect) * (1.0 - ReflCyl));
2981 : }
2982 3386 : } // CalcScreenTransmittance()
2983 :
2984 0 : void GetRelativePhiTheta(Real64 phiWin, Real64 thetaWin, Vector3<Real64> const &solcos, Real64 &phi, Real64 &theta)
2985 : {
2986 0 : phi = std::abs(std::acos(solcos.z) - phiWin);
2987 0 : theta = std::abs(std::atan2(solcos.x, solcos.y) - thetaWin);
2988 :
2989 0 : NormalizePhiTheta(phi, theta);
2990 0 : } // GetRelativePhiTheta()
2991 :
2992 : // Use reflection around Pi to normalize to the range 0 to Pi
2993 3248 : void NormalizePhiTheta(Real64 &phi, Real64 &theta)
2994 : {
2995 :
2996 3248 : while (phi > 2 * Constant::Pi)
2997 0 : phi -= 2 * Constant::Pi;
2998 3248 : if (phi > Constant::Pi) phi = 2 * Constant::Pi - phi;
2999 :
3000 3724 : while (theta > 2 * Constant::Pi)
3001 476 : theta -= 2 * Constant::Pi;
3002 3248 : if (theta > Constant::Pi) theta = 2 * Constant::Pi - theta;
3003 3248 : } // NormalizePhiTheta()
3004 :
3005 4692 : void GetPhiThetaIndices(Real64 phi, Real64 theta, Real64 dPhi, Real64 dTheta, int &iPhi1, int &iPhi2, int &iTheta1, int &iTheta2)
3006 : {
3007 4692 : iPhi1 = int(phi / dPhi);
3008 4692 : iPhi2 = (iPhi1 == maxIPhi - 1) ? iPhi1 : iPhi1 + 1;
3009 4692 : iTheta1 = int(theta / dTheta);
3010 4692 : iTheta2 = (iTheta1 == maxITheta - 1) ? iTheta1 : iTheta1 + 1;
3011 4692 : } // GetPhiThetaIndices()
3012 :
3013 : } // namespace EnergyPlus::Material
|