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