Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <string>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Array1D.hh>
54 : #include <ObjexxFCL/Array2D.hh>
55 : #include <ObjexxFCL/Fmath.hh>
56 :
57 : // EnergyPlus Headers
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataEnvironment.hh>
60 : #include <EnergyPlus/DataHeatBalFanSys.hh>
61 : #include <EnergyPlus/DataHeatBalance.hh>
62 : #include <EnergyPlus/DataIPShortCuts.hh>
63 : #include <EnergyPlus/DataRoomAirModel.hh>
64 : #include <EnergyPlus/DataRuntimeLanguage.hh>
65 : #include <EnergyPlus/DataStringGlobals.hh>
66 : #include <EnergyPlus/DataViewFactorInformation.hh>
67 : #include <EnergyPlus/DataZoneControls.hh>
68 : #include <EnergyPlus/DataZoneEquipment.hh>
69 : #include <EnergyPlus/EMSManager.hh>
70 : #include <EnergyPlus/General.hh>
71 : #include <EnergyPlus/GeneralRoutines.hh>
72 : #include <EnergyPlus/GlobalNames.hh>
73 : #include <EnergyPlus/HVACManager.hh>
74 : #include <EnergyPlus/HeatBalanceAirManager.hh>
75 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
76 : #include <EnergyPlus/InternalHeatGains.hh>
77 : #include <EnergyPlus/OutputProcessor.hh>
78 : #include <EnergyPlus/Psychrometrics.hh>
79 : #include <EnergyPlus/ScheduleManager.hh>
80 : #include <EnergyPlus/SystemAvailabilityManager.hh>
81 : #include <EnergyPlus/UtilityRoutines.hh>
82 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
83 :
84 : namespace EnergyPlus::HeatBalanceAirManager {
85 : // Module containing the air heat balance simulation routines
86 : // calculation (initialization) routines
87 :
88 : // MODULE INFORMATION:
89 : // AUTHOR Richard J. Liesen
90 : // DATE WRITTEN February 1998
91 : // MODIFIED May-July 2000 Joe Huang for Comis Link
92 :
93 : // PURPOSE OF THIS MODULE:
94 : // To encapsulate the data and algorithms required to
95 : // manage the air simluation heat balance on the building.
96 :
97 : // REFERENCES:
98 : // The heat balance method is outlined in the "Tarp Alogorithms Manual"
99 : // The methods are also summarized in many BSO Theses and papers.
100 :
101 : // OTHER NOTES:
102 : // This module was created from IBLAST subroutines
103 :
104 : enum class AirflowSpec
105 : {
106 : Invalid = -1,
107 : FlowPerZone,
108 : FlowPerArea,
109 : FlowPerExteriorArea,
110 : FlowPerExteriorWallArea,
111 : FlowPerPerson,
112 : AirChanges,
113 : Num
114 : };
115 : constexpr std::array<std::string_view, static_cast<int>(AirflowSpec::Num)> airflowSpecNamesUC = {
116 : "FLOW/ZONE", "FLOW/AREA", "FLOW/EXTERIORAREA", "FLOW/EXTERIORWALLAREA", "FLOW/PERSON", "AIRCHANGES/HOUR"};
117 :
118 : constexpr std::array<std::string_view, static_cast<int>(DataHeatBalance::VentilationType::Num)> ventilationTypeNamesUC = {
119 : "NATURAL", "INTAKE", "EXHAUST", "BALANCED"};
120 :
121 : constexpr std::array<std::string_view, static_cast<int>(DataHeatBalance::InfVentDensityBasis::Num)> infVentDensityBasisNamesUC = {
122 : "OUTDOOR", "STANDARD", "INDOOR"};
123 :
124 : constexpr std::array<std::string_view, static_cast<int>(RoomAir::RoomAirModel::Num)> roomAirModelNamesUC = {"USERDEFINED",
125 : "MIXING",
126 : "ONENODEDISPLACEMENTVENTILATION",
127 : "THREENODEDISPLACEMENTVENTILATION",
128 : "CROSSVENTILATION",
129 : "UNDERFLOORAIRDISTRIBUTIONINTERIOR",
130 : "UNDERFLOORAIRDISTRIBUTIONEXTERIOR",
131 : "AIRFLOWNETWORK"};
132 :
133 : constexpr std::array<std::string_view, static_cast<int>(RoomAir::CouplingScheme::Num)> couplingSchemeNamesUC = {"DIRECT", "INDIRECT"};
134 :
135 249946 : void ManageAirHeatBalance(EnergyPlusData &state)
136 : {
137 :
138 : // SUBROUTINE INFORMATION:
139 : // AUTHOR Richard Liesen
140 : // DATE WRITTEN February 1998
141 :
142 : // PURPOSE OF THIS SUBROUTINE:
143 : // This subroutine manages the heat air balance method of calculating
144 : // building thermal loads. It is called from the HeatBalanceManager
145 : // at the time step level. This driver manages the calls to all of
146 : // the other drivers and simulation algorithms.
147 :
148 : // Obtains and Allocates heat balance related parameters from input file
149 249946 : if (state.dataHeatBalAirMgr->ManageAirHeatBalanceGetInputFlag) {
150 103 : GetAirHeatBalanceInput(state);
151 103 : state.dataHeatBalAirMgr->ManageAirHeatBalanceGetInputFlag = false;
152 : }
153 :
154 249946 : InitAirHeatBalance(state); // Initialize all heat balance related parameters
155 :
156 : // Solve the zone heat balance 'Detailed' solution
157 : // Call the air surface heat balances
158 249946 : CalcHeatBalanceAir(state);
159 :
160 249945 : ReportZoneMeanAirTemp(state);
161 249945 : }
162 :
163 104 : void GetAirHeatBalanceInput(EnergyPlusData &state)
164 : {
165 :
166 : // SUBROUTINE INFORMATION:
167 : // AUTHOR Richard Liesen
168 : // DATE WRITTEN February 1998
169 :
170 : // PURPOSE OF THIS SUBROUTINE:
171 : // This subroutine is the main routine to call other input routines
172 :
173 : // METHODOLOGY EMPLOYED:
174 : // Uses the status flags to trigger events.
175 :
176 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
177 104 : bool ErrorsFound = false;
178 :
179 104 : GetAirFlowFlag(state, ErrorsFound);
180 :
181 104 : SetZoneMassConservationFlag(state);
182 :
183 : // get input parameters for modeling of room air flow
184 104 : GetRoomAirModelParameters(state, ErrorsFound);
185 :
186 104 : if (ErrorsFound) {
187 0 : ShowFatalError(state, "GetAirHeatBalanceInput: Errors found in getting Air inputs");
188 : }
189 104 : }
190 :
191 105 : void GetAirFlowFlag(EnergyPlusData &state, bool &ErrorsFound) // Set to true if errors found
192 : {
193 :
194 : // SUBROUTINE INFORMATION:
195 : // AUTHOR Garrett Westmacott
196 : // DATE WRITTEN February 2000
197 : // MODIFIED Oct 2003, FCW: Change "Infiltration-Air Change Rate" from Sum to State
198 :
199 : // PURPOSE OF THIS SUBROUTINE:
200 : // This subroutine calls the routine to get simple air flow input data.
201 :
202 : // METHODOLOGY EMPLOYED:
203 : // Modelled after 'Modual Example' in Guide for Module Developers
204 :
205 105 : state.dataHeatBal->AirFlowFlag = true; // UseSimpleAirFlow;
206 :
207 105 : GetSimpleAirModelInputs(state, ErrorsFound);
208 105 : if (state.dataHeatBal->TotInfiltration + state.dataHeatBal->TotVentilation + state.dataHeatBal->TotMixing + state.dataHeatBal->TotCrossMixing +
209 105 : state.dataHeatBal->TotRefDoorMixing >
210 : 0) {
211 : static constexpr std::string_view Format_720("! <AirFlow Model>, Simple\n AirFlow Model, {}\n");
212 14 : print(state.files.eio, Format_720, "Simple");
213 : }
214 105 : }
215 :
216 111 : void SetZoneMassConservationFlag(EnergyPlusData &state)
217 : {
218 :
219 : // SUBROUTINE INFORMATION :
220 : // AUTHOR Bereket Nigusse, FSEC
221 : // DATE WRITTEN February 2014
222 :
223 : // PURPOSE OF THIS SUBROUTINE :
224 : // This subroutine sets the zone mass conservation flag to true.
225 :
226 118 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance &&
227 7 : state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) {
228 14 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
229 8 : state.dataHeatBalFanSys->ZoneMassBalanceFlag(state.dataHeatBal->Mixing(Loop).ZonePtr) = true;
230 8 : state.dataHeatBalFanSys->ZoneMassBalanceFlag(state.dataHeatBal->Mixing(Loop).FromZone) = true;
231 : }
232 : }
233 111 : }
234 :
235 120 : void GetSimpleAirModelInputs(EnergyPlusData &state, bool &ErrorsFound) // IF errors found in input
236 : {
237 :
238 : // SUBROUTINE INFORMATION:
239 : // AUTHOR Linda Lawrie
240 : // DATE WRITTEN July 2000
241 : // MODIFIED Oct 2003,FCW: change "Infiltration-Air Change Rate" from Sum to State
242 : // MODIFIED Jan 2008,LG: Allow multiple infiltration and ventilation objects per zone
243 : // May 2009, BG: added calls to setup for possible EMS override
244 : // August 2011, TKS: added refrigeration door mixing
245 :
246 : // PURPOSE OF THIS SUBROUTINE:
247 : // This subroutine gets the input for the "simple" air flow model.
248 :
249 : // SUBROUTINE PARAMETER DEFINITIONS:
250 120 : Real64 constexpr VentilTempLimit = 100.0; // degrees Celsius
251 120 : Real64 constexpr MixingTempLimit = 100.0; // degrees Celsius
252 120 : Real64 constexpr VentilWSLimit = 40.0; // m/s
253 : static constexpr std::string_view RoutineName("GetSimpleAirModelInputs: "); // include trailing blank space
254 : static constexpr std::string_view routineName = "GetSimpleAirModelInputs";
255 : // Refrigeration Door Mixing Protection types, factors used to moderate mixing flow.
256 120 : Real64 constexpr RefDoorNone = 0.0;
257 120 : Real64 constexpr RefDoorAirCurtain = 0.5;
258 120 : Real64 constexpr RefDoorStripCurtain = 0.9;
259 :
260 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
261 : int NumAlpha; // Number of Alphas for each GetobjectItem call
262 : int NumNumber; // Number of Numbers for each GetobjectItem call
263 : int NumArgs;
264 : int IOStat;
265 120 : Array1D_string cAlphaFieldNames;
266 120 : Array1D_string cNumericFieldNames;
267 120 : Array1D_bool lNumericFieldBlanks;
268 120 : Array1D_bool lAlphaFieldBlanks;
269 120 : Array1D_string cAlphaArgs;
270 120 : Array1D<Real64> rNumericArgs;
271 :
272 120 : Array1D_bool RepVarSet;
273 :
274 120 : std::string StringOut;
275 120 : std::string NameThisObject;
276 120 : Array1D<Real64> TotInfilVentFlow;
277 120 : Array1D<Real64> TotMixingFlow;
278 120 : Array1D<Real64> ZoneMixingNum;
279 : int ConnectionNumber;
280 : int ZoneNumA;
281 : int ZoneNumB;
282 :
283 : // Formats
284 : static constexpr std::string_view Format_720(" {} Airflow Stats Nominal, {},{},{},{:.2R},{:.1R},");
285 : static constexpr std::string_view Format_721(
286 : "! <{} Airflow Stats Nominal>,Name,Schedule Name,Zone Name, Zone Floor Area {{m2}}, # Zone Occupants,{}\n");
287 : static constexpr std::string_view Format_722(" {}, {}\n");
288 :
289 120 : RepVarSet.dimension(state.dataGlobal->NumOfZones, true);
290 :
291 : // Following used for reporting
292 120 : state.dataHeatBal->ZnAirRpt.allocate(state.dataGlobal->NumOfZones);
293 120 : if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
294 8 : state.dataHeatBal->spaceAirRpt.allocate(state.dataGlobal->numSpaces);
295 : }
296 :
297 283 : for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
298 163 : std::string const &name = state.dataHeatBal->Zone(Loop).Name;
299 163 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(Loop);
300 163 : thisZnAirRpt.setUpOutputVars(state, DataStringGlobals::zonePrefix, name);
301 163 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
302 5 : for (int spaceNum : state.dataHeatBal->Zone(Loop).spaceIndexes) {
303 3 : state.dataHeatBal->spaceAirRpt(spaceNum).setUpOutputVars(
304 3 : state, DataStringGlobals::spacePrefix, state.dataHeatBal->space(spaceNum).Name);
305 : }
306 : }
307 :
308 : // CurrentModuleObject='Zone'
309 163 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
310 0 : SetupOutputVariable(state,
311 : "Zone Phase Change Material Melting Enthalpy",
312 : Constant::Units::J_kg,
313 0 : thisZnAirRpt.SumEnthalpyM,
314 : OutputProcessor::TimeStepType::Zone,
315 : OutputProcessor::StoreType::Average,
316 : name);
317 0 : SetupOutputVariable(state,
318 : "Zone Phase Change Material Freezing Enthalpy",
319 : Constant::Units::J_kg,
320 0 : thisZnAirRpt.SumEnthalpyH,
321 : OutputProcessor::TimeStepType::Zone,
322 : OutputProcessor::StoreType::Average,
323 : name);
324 : }
325 :
326 326 : SetupOutputVariable(state,
327 : "Zone Exfiltration Heat Transfer Rate",
328 : Constant::Units::W,
329 163 : thisZnAirRpt.ExfilTotalLoss,
330 : OutputProcessor::TimeStepType::System,
331 : OutputProcessor::StoreType::Average,
332 : name);
333 326 : SetupOutputVariable(state,
334 : "Zone Exfiltration Sensible Heat Transfer Rate",
335 : Constant::Units::W,
336 163 : thisZnAirRpt.ExfilSensiLoss,
337 : OutputProcessor::TimeStepType::System,
338 : OutputProcessor::StoreType::Average,
339 : name);
340 326 : SetupOutputVariable(state,
341 : "Zone Exfiltration Latent Heat Transfer Rate",
342 : Constant::Units::W,
343 163 : thisZnAirRpt.ExfilLatentLoss,
344 : OutputProcessor::TimeStepType::System,
345 : OutputProcessor::StoreType::Average,
346 : name);
347 326 : SetupOutputVariable(state,
348 : "Zone Exhaust Air Heat Transfer Rate",
349 : Constant::Units::W,
350 163 : thisZnAirRpt.ExhTotalLoss,
351 : OutputProcessor::TimeStepType::System,
352 : OutputProcessor::StoreType::Average,
353 : name);
354 326 : SetupOutputVariable(state,
355 : "Zone Exhaust Air Sensible Heat Transfer Rate",
356 : Constant::Units::W,
357 163 : thisZnAirRpt.ExhSensiLoss,
358 : OutputProcessor::TimeStepType::System,
359 : OutputProcessor::StoreType::Average,
360 : name);
361 326 : SetupOutputVariable(state,
362 : "Zone Exhaust Air Latent Heat Transfer Rate",
363 : Constant::Units::W,
364 163 : thisZnAirRpt.ExhLatentLoss,
365 : OutputProcessor::TimeStepType::System,
366 : OutputProcessor::StoreType::Average,
367 : name);
368 : }
369 :
370 480 : SetupOutputVariable(state,
371 : "Site Total Zone Exfiltration Heat Loss",
372 : Constant::Units::J,
373 120 : state.dataHeatBal->ZoneTotalExfiltrationHeatLoss,
374 : OutputProcessor::TimeStepType::System,
375 : OutputProcessor::StoreType::Sum,
376 : "Environment");
377 480 : SetupOutputVariable(state,
378 : "Site Total Zone Exhaust Air Heat Loss",
379 : Constant::Units::J,
380 120 : state.dataHeatBal->ZoneTotalExhaustHeatLoss,
381 : OutputProcessor::TimeStepType::System,
382 : OutputProcessor::StoreType::Sum,
383 : "Environment");
384 :
385 120 : std::string cCurrentModuleObject = "ZoneAirBalance:OutdoorAir";
386 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
387 120 : int maxAlpha = NumAlpha;
388 120 : int maxNumber = NumNumber;
389 120 : cCurrentModuleObject = "ZoneInfiltration:EffectiveLeakageArea";
390 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
391 120 : maxAlpha = max(NumAlpha, maxAlpha);
392 120 : maxNumber = max(NumNumber, maxNumber);
393 120 : cCurrentModuleObject = "ZoneInfiltration:FlowCoefficient";
394 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
395 120 : maxAlpha = max(NumAlpha, maxAlpha);
396 120 : maxNumber = max(NumNumber, maxNumber);
397 120 : cCurrentModuleObject = "ZoneInfiltration:DesignFlowRate";
398 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
399 120 : maxAlpha = max(NumAlpha, maxAlpha);
400 120 : maxNumber = max(NumNumber, maxNumber);
401 120 : cCurrentModuleObject = "ZoneVentilation:DesignFlowRate";
402 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
403 120 : maxAlpha = max(NumAlpha, maxAlpha);
404 120 : maxNumber = max(NumNumber, maxNumber);
405 120 : cCurrentModuleObject = "ZoneVentilation:WindandStackOpenArea";
406 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
407 120 : maxAlpha = max(NumAlpha, maxAlpha);
408 120 : maxNumber = max(NumNumber, maxNumber);
409 120 : cCurrentModuleObject = "ZoneMixing";
410 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
411 120 : maxAlpha = max(NumAlpha, maxAlpha);
412 120 : maxNumber = max(NumNumber, maxNumber);
413 120 : cCurrentModuleObject = "ZoneCrossMixing";
414 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
415 120 : maxAlpha = max(NumAlpha, maxAlpha);
416 120 : maxNumber = max(NumNumber, maxNumber);
417 120 : cCurrentModuleObject = "ZoneRefrigerationDoorMixing";
418 120 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, NumArgs, NumAlpha, NumNumber);
419 120 : maxAlpha = max(NumAlpha, maxAlpha);
420 120 : maxNumber = max(NumNumber, maxNumber);
421 :
422 120 : cAlphaArgs.allocate(maxAlpha);
423 120 : cAlphaFieldNames.allocate(maxAlpha);
424 120 : cNumericFieldNames.allocate(maxNumber);
425 120 : rNumericArgs.dimension(maxNumber, 0.0);
426 120 : lAlphaFieldBlanks.dimension(maxAlpha, true);
427 120 : lNumericFieldBlanks.dimension(maxNumber, true);
428 :
429 120 : cCurrentModuleObject = "ZoneAirBalance:OutdoorAir";
430 120 : state.dataHeatBal->TotZoneAirBalance = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
431 :
432 120 : state.dataHeatBal->ZoneAirBalance.allocate(state.dataHeatBal->TotZoneAirBalance);
433 :
434 122 : for (int Loop = 1; Loop <= state.dataHeatBal->TotZoneAirBalance; ++Loop) {
435 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
436 : cCurrentModuleObject,
437 : Loop,
438 : cAlphaArgs,
439 : NumAlpha,
440 : rNumericArgs,
441 : NumNumber,
442 : IOStat,
443 : lNumericFieldBlanks,
444 : lAlphaFieldBlanks,
445 : cAlphaFieldNames,
446 : cNumericFieldNames);
447 :
448 2 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
449 2 : bool IsNotOK = false;
450 2 : auto &thisZoneAirBalance = state.dataHeatBal->ZoneAirBalance(Loop);
451 2 : thisZoneAirBalance.Name = cAlphaArgs(1);
452 2 : thisZoneAirBalance.ZoneName = cAlphaArgs(2);
453 2 : thisZoneAirBalance.ZonePtr = Util::FindItemInList(cAlphaArgs(2), state.dataHeatBal->Zone);
454 2 : if (thisZoneAirBalance.ZonePtr == 0) {
455 0 : ShowSevereError(state,
456 0 : format(R"({}{}="{}", invalid (not found) {}="{}".)",
457 : RoutineName,
458 : cCurrentModuleObject,
459 : cAlphaArgs(1),
460 : cAlphaFieldNames(2),
461 : cAlphaArgs(2)));
462 0 : ErrorsFound = true;
463 : } else {
464 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).zoneOABalanceIndex = Loop;
465 : }
466 2 : GlobalNames::IntraObjUniquenessCheck(
467 4 : state, cAlphaArgs(2), cCurrentModuleObject, cAlphaFieldNames(2), state.dataHeatBalAirMgr->UniqueZoneNames, IsNotOK);
468 2 : if (IsNotOK) {
469 2 : ShowSevereError(state,
470 2 : format(R"({}{}="{}", a duplicated object {}="{}" is found.)",
471 : RoutineName,
472 : cCurrentModuleObject,
473 : cAlphaArgs(1),
474 : cAlphaFieldNames(2),
475 : cAlphaArgs(2)));
476 1 : ShowContinueError(state, format("A zone can only have one {} object.", cCurrentModuleObject));
477 1 : ErrorsFound = true;
478 : }
479 :
480 : {
481 2 : thisZoneAirBalance.BalanceMethod = static_cast<DataHeatBalance::AirBalance>(
482 2 : getEnumValue(DataHeatBalance::AirBalanceTypeNamesUC,
483 4 : Util::makeUPPER(cAlphaArgs(3)))); // Air balance method type character input-->convert to enum
484 2 : if (thisZoneAirBalance.BalanceMethod == DataHeatBalance::AirBalance::Invalid) {
485 0 : thisZoneAirBalance.BalanceMethod = DataHeatBalance::AirBalance::None;
486 0 : ShowWarningError(state,
487 0 : format("{}{} = {} not valid choice for {}={}",
488 : RoutineName,
489 : cAlphaFieldNames(3),
490 : cAlphaArgs(3),
491 : cCurrentModuleObject,
492 : cAlphaArgs(1)));
493 0 : ShowContinueError(state, "The default choice \"NONE\" is assigned");
494 : }
495 : }
496 :
497 2 : thisZoneAirBalance.InducedAirRate = rNumericArgs(1);
498 2 : if (rNumericArgs(1) < 0.0) {
499 0 : ShowSevereError(state,
500 0 : format("{}{}=\"{}\", invalid Induced Outdoor Air Due to Duct Leakage Unbalance specification [<0.0]={:.3R}",
501 : RoutineName,
502 : cCurrentModuleObject,
503 : cAlphaArgs(1),
504 : rNumericArgs(1)));
505 0 : ErrorsFound = true;
506 : }
507 :
508 2 : if (lAlphaFieldBlanks(4)) {
509 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(4));
510 2 : } else if ((thisZoneAirBalance.inducedAirSched = Sched::GetSchedule(state, cAlphaArgs(4))) == nullptr) {
511 2 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
512 2 : ErrorsFound = true;
513 0 : } else if (!thisZoneAirBalance.inducedAirSched->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
514 0 : Sched::ShowSevereBadMinMax(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4), Clusive::In, 0.0, Clusive::In, 1.0);
515 0 : ErrorsFound = true;
516 : }
517 :
518 : // Check whether this zone is also controlled by hybrid ventilation object with ventilation control option or not
519 2 : bool ControlFlag = Avail::GetHybridVentilationControlStatus(state, thisZoneAirBalance.ZonePtr);
520 2 : if (ControlFlag && thisZoneAirBalance.BalanceMethod == DataHeatBalance::AirBalance::Quadrature) {
521 0 : thisZoneAirBalance.BalanceMethod = DataHeatBalance::AirBalance::None;
522 0 : ShowWarningError(
523 : state,
524 0 : format("{} = {}: This Zone ({}) is controlled by AvailabilityManager:HybridVentilation with Simple Airflow Control Type option.",
525 : cCurrentModuleObject,
526 0 : thisZoneAirBalance.Name,
527 : cAlphaArgs(2)));
528 0 : ShowContinueError(state,
529 : "Air balance method type QUADRATURE and Simple Airflow Control Type cannot co-exist. The NONE method is assigned");
530 : }
531 :
532 2 : if (thisZoneAirBalance.BalanceMethod == DataHeatBalance::AirBalance::Quadrature) {
533 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).zoneOAQuadratureSum = true;
534 4 : SetupOutputVariable(state,
535 : "Zone Combined Outdoor Air Sensible Heat Loss Energy",
536 : Constant::Units::J,
537 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceHeatLoss,
538 : OutputProcessor::TimeStepType::System,
539 : OutputProcessor::StoreType::Sum,
540 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
541 4 : SetupOutputVariable(state,
542 : "Zone Combined Outdoor Air Sensible Heat Gain Energy",
543 : Constant::Units::J,
544 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceHeatGain,
545 : OutputProcessor::TimeStepType::System,
546 : OutputProcessor::StoreType::Sum,
547 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
548 4 : SetupOutputVariable(state,
549 : "Zone Combined Outdoor Air Latent Heat Loss Energy",
550 : Constant::Units::J,
551 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceLatentLoss,
552 : OutputProcessor::TimeStepType::System,
553 : OutputProcessor::StoreType::Sum,
554 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
555 4 : SetupOutputVariable(state,
556 : "Zone Combined Outdoor Air Latent Heat Gain Energy",
557 : Constant::Units::J,
558 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceLatentGain,
559 : OutputProcessor::TimeStepType::System,
560 : OutputProcessor::StoreType::Sum,
561 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
562 4 : SetupOutputVariable(state,
563 : "Zone Combined Outdoor Air Total Heat Loss Energy",
564 : Constant::Units::J,
565 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceTotalLoss,
566 : OutputProcessor::TimeStepType::System,
567 : OutputProcessor::StoreType::Sum,
568 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
569 4 : SetupOutputVariable(state,
570 : "Zone Combined Outdoor Air Total Heat Gain Energy",
571 : Constant::Units::J,
572 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceTotalGain,
573 : OutputProcessor::TimeStepType::System,
574 : OutputProcessor::StoreType::Sum,
575 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
576 4 : SetupOutputVariable(state,
577 : "Zone Combined Outdoor Air Current Density Volume Flow Rate",
578 : Constant::Units::m3_s,
579 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceVdotCurDensity,
580 : OutputProcessor::TimeStepType::System,
581 : OutputProcessor::StoreType::Sum,
582 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
583 4 : SetupOutputVariable(state,
584 : "Zone Combined Outdoor Air Standard Density Volume Flow Rate",
585 : Constant::Units::m3_s,
586 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceVdotStdDensity,
587 : OutputProcessor::TimeStepType::System,
588 : OutputProcessor::StoreType::Sum,
589 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
590 4 : SetupOutputVariable(state,
591 : "Zone Combined Outdoor Air Current Density Volume",
592 : Constant::Units::m3,
593 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceVolumeCurDensity,
594 : OutputProcessor::TimeStepType::System,
595 : OutputProcessor::StoreType::Sum,
596 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
597 4 : SetupOutputVariable(state,
598 : "Zone Combined Outdoor Air Standard Density Volume",
599 : Constant::Units::m3,
600 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceVolumeStdDensity,
601 : OutputProcessor::TimeStepType::System,
602 : OutputProcessor::StoreType::Sum,
603 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
604 4 : SetupOutputVariable(state,
605 : "Zone Combined Outdoor Air Mass",
606 : Constant::Units::kg,
607 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceMass,
608 : OutputProcessor::TimeStepType::System,
609 : OutputProcessor::StoreType::Sum,
610 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
611 4 : SetupOutputVariable(state,
612 : "Zone Combined Outdoor Air Mass Flow Rate",
613 : Constant::Units::kg_s,
614 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceMdot,
615 : OutputProcessor::TimeStepType::System,
616 : OutputProcessor::StoreType::Average,
617 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
618 4 : SetupOutputVariable(state,
619 : "Zone Combined Outdoor Air Changes per Hour",
620 : Constant::Units::ach,
621 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceAirChangeRate,
622 : OutputProcessor::TimeStepType::System,
623 : OutputProcessor::StoreType::Average,
624 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
625 4 : SetupOutputVariable(state,
626 : "Zone Combined Outdoor Air Fan Electricity Energy",
627 : Constant::Units::J,
628 2 : state.dataHeatBal->ZnAirRpt(thisZoneAirBalance.ZonePtr).OABalanceFanElec,
629 : OutputProcessor::TimeStepType::System,
630 : OutputProcessor::StoreType::Sum,
631 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name,
632 : Constant::eResource::Electricity,
633 : OutputProcessor::Group::Building,
634 : OutputProcessor::EndUseCat::Fans,
635 : "Ventilation (simple)",
636 2 : state.dataHeatBal->Zone(thisZoneAirBalance.ZonePtr).Name);
637 : }
638 : }
639 :
640 : // Set up and process ZoneInfiltration:* inputs
641 :
642 120 : cCurrentModuleObject = "ZoneInfiltration:DesignFlowRate";
643 120 : int numDesignFlowInfiltrationObjects = 0;
644 120 : int totDesignFlowInfiltration = 0; // Total ZoneInfiltration:DesignFlowRate instances after expansion to spaces
645 120 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> infiltrationDesignFlowRateObjects;
646 120 : InternalHeatGains::setupIHGZonesAndSpaces(
647 : state, cCurrentModuleObject, infiltrationDesignFlowRateObjects, numDesignFlowInfiltrationObjects, totDesignFlowInfiltration, ErrorsFound);
648 :
649 120 : cCurrentModuleObject = "ZoneInfiltration:EffectiveLeakageArea";
650 120 : int numLeakageAreaInfiltrationObjects = 0;
651 120 : int totLeakageAreaInfiltration = 0; // Total ZoneInfiltration:EffectiveLeakageArea instances after expansion to spaces
652 120 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> infiltrationLeakageAreaObjects;
653 120 : bool const zoneListNotAllowed = true;
654 120 : InternalHeatGains::setupIHGZonesAndSpaces(state,
655 : cCurrentModuleObject,
656 : infiltrationLeakageAreaObjects,
657 : numLeakageAreaInfiltrationObjects,
658 : totLeakageAreaInfiltration,
659 : ErrorsFound,
660 : zoneListNotAllowed);
661 :
662 120 : cCurrentModuleObject = "ZoneInfiltration:FlowCoefficient";
663 120 : int numFlowCoefficientInfiltrationObjects = 0;
664 120 : int totFlowCoefficientInfiltration = 0; // Total ZoneInfiltration:FlowCoefficient instances after expansion to spaces
665 120 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> infiltrationFlowCoefficientObjects;
666 120 : InternalHeatGains::setupIHGZonesAndSpaces(state,
667 : cCurrentModuleObject,
668 : infiltrationFlowCoefficientObjects,
669 : numFlowCoefficientInfiltrationObjects,
670 : totFlowCoefficientInfiltration,
671 : ErrorsFound,
672 : zoneListNotAllowed);
673 :
674 120 : state.dataHeatBal->TotInfiltration = totDesignFlowInfiltration + totLeakageAreaInfiltration + totFlowCoefficientInfiltration;
675 120 : state.dataHeatBal->Infiltration.allocate(state.dataHeatBal->TotInfiltration);
676 120 : state.dataHeatBalAirMgr->UniqueInfiltrationNames.reserve(static_cast<unsigned>(state.dataHeatBal->TotInfiltration));
677 :
678 120 : int infiltrationNum = 0;
679 120 : if (totDesignFlowInfiltration > 0) {
680 21 : cCurrentModuleObject = "ZoneInfiltration:DesignFlowRate";
681 65 : for (int infilInputNum = 1; infilInputNum <= numDesignFlowInfiltrationObjects; ++infilInputNum) {
682 :
683 44 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
684 : cCurrentModuleObject,
685 : infilInputNum,
686 : cAlphaArgs,
687 : NumAlpha,
688 : rNumericArgs,
689 : NumNumber,
690 : IOStat,
691 : lNumericFieldBlanks,
692 : lAlphaFieldBlanks,
693 : cAlphaFieldNames,
694 : cNumericFieldNames);
695 :
696 44 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
697 : // Create one Infiltration instance for every space associated with this input object
698 44 : auto &thisInfiltrationInput = infiltrationDesignFlowRateObjects(infilInputNum);
699 93 : for (int Item1 = 1; Item1 <= thisInfiltrationInput.numOfSpaces; ++Item1) {
700 49 : ++infiltrationNum;
701 49 : auto &thisInfiltration = state.dataHeatBal->Infiltration(infiltrationNum);
702 49 : thisInfiltration.Name = thisInfiltrationInput.names(Item1);
703 49 : thisInfiltration.spaceIndex = thisInfiltrationInput.spaceNums(Item1);
704 49 : auto &thisSpace = state.dataHeatBal->space(thisInfiltration.spaceIndex);
705 49 : thisInfiltration.ZonePtr = thisSpace.zoneNum;
706 49 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
707 :
708 49 : thisInfiltration.ModelType = DataHeatBalance::InfiltrationModelType::DesignFlowRate;
709 :
710 49 : if (lAlphaFieldBlanks(3)) {
711 10 : thisInfiltration.sched =
712 10 : Sched::GetScheduleAlwaysOn(state); // This is not an availability schedule per se, but does default to Constant-1.0
713 39 : } else if ((thisInfiltration.sched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
714 0 : if (Item1 == 1) { // avoid repeated error messages from the same input object
715 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
716 0 : ErrorsFound = true;
717 : }
718 : }
719 :
720 : // Set space flow fractions
721 : // Infiltration equipment design level calculation method.
722 49 : AirflowSpec flow = static_cast<AirflowSpec>(getEnumValue(airflowSpecNamesUC, cAlphaArgs(4))); // NOLINT(modernize-use-auto)
723 49 : switch (flow) {
724 37 : case AirflowSpec::FlowPerZone:
725 37 : if (lNumericFieldBlanks(1)) {
726 0 : ShowWarningError(state,
727 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Infiltration will result.",
728 : RoutineName,
729 : cCurrentModuleObject,
730 0 : thisInfiltration.Name,
731 : cAlphaFieldNames(4),
732 : cNumericFieldNames(1)));
733 : } else {
734 37 : Real64 spaceFrac = 1.0;
735 37 : if (!thisInfiltrationInput.spaceListActive && (thisInfiltrationInput.numOfSpaces > 1)) {
736 2 : Real64 const zoneVolume = thisZone.Volume;
737 2 : if (zoneVolume > 0.0) {
738 2 : spaceFrac = thisSpace.Volume / zoneVolume;
739 : } else {
740 0 : ShowSevereError(state, format("{}Zone volume is zero when allocating Infiltration to Spaces.", RoutineName));
741 0 : ShowContinueError(
742 : state,
743 0 : format("Occurs for {}=\"{}\" in Zone=\"{}\".", cCurrentModuleObject, thisInfiltrationInput.Name, thisZone.Name));
744 0 : ErrorsFound = true;
745 : }
746 : }
747 :
748 37 : thisInfiltration.DesignLevel = rNumericArgs(1) * spaceFrac;
749 : }
750 37 : break;
751 :
752 10 : case AirflowSpec::FlowPerArea:
753 10 : if (thisInfiltration.ZonePtr != 0) {
754 10 : if (rNumericArgs(2) >= 0.0) {
755 10 : thisInfiltration.DesignLevel = rNumericArgs(2) * thisSpace.FloorArea;
756 10 : if (thisInfiltration.ZonePtr > 0) {
757 10 : if (thisSpace.FloorArea <= 0.0) {
758 0 : ShowWarningError(state,
759 0 : format("{}{}=\"{}\", {} specifies {}, but Space Floor Area = 0. 0 Infiltration will result.",
760 : RoutineName,
761 : cCurrentModuleObject,
762 0 : thisInfiltration.Name,
763 : cAlphaFieldNames(4),
764 : cNumericFieldNames(2)));
765 : }
766 : }
767 : } else {
768 0 : ShowSevereError(state,
769 0 : format("{}{}=\"{}\", invalid flow/area specification [<0.0]={:.3R}",
770 : RoutineName,
771 : cCurrentModuleObject,
772 0 : thisInfiltration.Name,
773 : rNumericArgs(2)));
774 0 : ErrorsFound = true;
775 : }
776 : }
777 10 : if (lNumericFieldBlanks(2)) {
778 0 : ShowWarningError(state,
779 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Infiltration will result.",
780 : RoutineName,
781 : cCurrentModuleObject,
782 0 : thisInfiltration.Name,
783 : cAlphaFieldNames(4),
784 : cNumericFieldNames(2)));
785 : }
786 10 : break;
787 :
788 0 : case AirflowSpec::FlowPerExteriorArea:
789 0 : if (thisInfiltration.ZonePtr != 0) {
790 0 : if (rNumericArgs(3) >= 0.0) {
791 0 : thisInfiltration.DesignLevel = rNumericArgs(3) * thisSpace.ExteriorTotalSurfArea;
792 0 : if (thisSpace.ExteriorTotalSurfArea <= 0.0) {
793 0 : ShowWarningError(state,
794 0 : format("{}{}=\"{}\", {} specifies {}, but Exterior Surface Area = 0. 0 Infiltration will result.",
795 : RoutineName,
796 : cCurrentModuleObject,
797 0 : thisInfiltration.Name,
798 : cAlphaFieldNames(4),
799 : cNumericFieldNames(3)));
800 : }
801 : } else {
802 0 : ShowSevereError(state,
803 0 : format("{}{} = \"{}\", invalid flow/exteriorarea specification [<0.0]={:.3R}",
804 : RoutineName,
805 : cCurrentModuleObject,
806 0 : thisInfiltration.Name,
807 : rNumericArgs(3)));
808 0 : ErrorsFound = true;
809 : }
810 : }
811 0 : if (lNumericFieldBlanks(3)) {
812 0 : ShowWarningError(state,
813 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Infiltration will result.",
814 : RoutineName,
815 : cCurrentModuleObject,
816 0 : thisInfiltration.Name,
817 : cAlphaFieldNames(4),
818 : cNumericFieldNames(3)));
819 : }
820 0 : break;
821 :
822 0 : case AirflowSpec::FlowPerExteriorWallArea:
823 0 : if (thisInfiltration.ZonePtr != 0) {
824 0 : if (rNumericArgs(3) >= 0.0) {
825 0 : thisInfiltration.DesignLevel = rNumericArgs(3) * thisSpace.ExtGrossWallArea;
826 0 : if (thisSpace.ExtGrossWallArea <= 0.0) {
827 0 : ShowWarningError(state,
828 0 : format("{}{}=\"{}\", {} specifies {}, but Exterior Wall Area = 0. 0 Infiltration will result.",
829 : RoutineName,
830 : cCurrentModuleObject,
831 0 : thisInfiltration.Name,
832 : cAlphaFieldNames(4),
833 : cNumericFieldNames(3)));
834 : }
835 : } else {
836 0 : ShowSevereError(state,
837 0 : format("{}{} = \"{}\", invalid flow/exteriorwallarea specification [<0.0]={:.3R}",
838 : RoutineName,
839 : cCurrentModuleObject,
840 0 : thisInfiltration.Name,
841 : rNumericArgs(3)));
842 0 : ErrorsFound = true;
843 : }
844 : }
845 0 : if (lNumericFieldBlanks(3)) {
846 0 : ShowWarningError(state,
847 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Infiltration will result.",
848 : RoutineName,
849 : cCurrentModuleObject,
850 0 : thisInfiltration.Name,
851 : cAlphaFieldNames(4),
852 : cNumericFieldNames(3)));
853 : }
854 0 : break;
855 :
856 2 : case AirflowSpec::AirChanges:
857 2 : if (thisInfiltration.spaceIndex != 0) {
858 2 : if (rNumericArgs(4) >= 0.0) {
859 2 : thisInfiltration.DesignLevel = rNumericArgs(4) * thisSpace.Volume / Constant::rSecsInHour;
860 2 : if (thisSpace.Volume <= 0.0) {
861 0 : ShowWarningError(state,
862 0 : format("{}{}=\"{}\", {} specifies {}, but Space Volume = 0. 0 Infiltration will result.",
863 : RoutineName,
864 : cCurrentModuleObject,
865 0 : thisInfiltration.Name,
866 : cAlphaFieldNames(4),
867 : cNumericFieldNames(4)));
868 : }
869 : } else {
870 0 : ShowSevereError(state,
871 0 : format("{}In {} = \"{}\", invalid ACH (air changes per hour) specification [<0.0]={:.3R}",
872 : RoutineName,
873 : cCurrentModuleObject,
874 0 : thisInfiltration.Name,
875 : rNumericArgs(4)));
876 0 : ErrorsFound = true;
877 : }
878 : }
879 2 : if (lNumericFieldBlanks(4)) {
880 0 : ShowWarningError(state,
881 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Infiltration will result.",
882 : RoutineName,
883 : cCurrentModuleObject,
884 0 : thisInfiltrationInput.Name,
885 : cAlphaFieldNames(4),
886 : cNumericFieldNames(4)));
887 : }
888 2 : break;
889 :
890 0 : default:
891 0 : if (Item1 == 1) {
892 0 : ShowSevereError(
893 : state,
894 0 : format("{}{}=\"{}\", invalid calculation method={}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(4)));
895 0 : ErrorsFound = true;
896 : }
897 : }
898 :
899 49 : thisInfiltration.ConstantTermCoef = !lNumericFieldBlanks(5) ? rNumericArgs(5) : 1.0;
900 49 : thisInfiltration.TemperatureTermCoef = !lNumericFieldBlanks(6) ? rNumericArgs(6) : 0.0;
901 49 : thisInfiltration.VelocityTermCoef = !lNumericFieldBlanks(7) ? rNumericArgs(7) : 0.0;
902 49 : thisInfiltration.VelocitySQTermCoef = !lNumericFieldBlanks(8) ? rNumericArgs(8) : 0.0;
903 :
904 49 : if (thisInfiltration.ConstantTermCoef == 0.0 && thisInfiltration.TemperatureTermCoef == 0.0 &&
905 22 : thisInfiltration.VelocityTermCoef == 0.0 && thisInfiltration.VelocitySQTermCoef == 0.0) {
906 0 : if (Item1 == 1) {
907 0 : ShowWarningError(
908 : state,
909 0 : format(
910 : R"({}{}="{}", in {}="{}".)", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaFieldNames(2), cAlphaArgs(2)));
911 0 : ShowContinueError(state, "Infiltration Coefficients are all zero. No Infiltration will be reported.");
912 : }
913 : }
914 49 : thisInfiltration.densityBasis = static_cast<DataHeatBalance::InfVentDensityBasis>(
915 49 : getEnumValue(infVentDensityBasisNamesUC, cAlphaArgs(5))); // NOLINT(modernize-use-auto)
916 : }
917 : }
918 : }
919 :
920 120 : if (totLeakageAreaInfiltration > 0) {
921 1 : cCurrentModuleObject = "ZoneInfiltration:EffectiveLeakageArea";
922 2 : for (int infilInputNum = 1; infilInputNum <= numLeakageAreaInfiltrationObjects; ++infilInputNum) {
923 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
924 : cCurrentModuleObject,
925 : infilInputNum,
926 : cAlphaArgs,
927 : NumAlpha,
928 : rNumericArgs,
929 : NumNumber,
930 : IOStat,
931 : lNumericFieldBlanks,
932 : lAlphaFieldBlanks,
933 : cAlphaFieldNames,
934 : cNumericFieldNames);
935 :
936 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
937 :
938 : // Create one Infiltration instance for every space associated with this input object
939 1 : auto &thisInfiltrationInput = infiltrationLeakageAreaObjects(infilInputNum);
940 2 : for (int Item1 = 1; Item1 <= thisInfiltrationInput.numOfSpaces; ++Item1) {
941 1 : ++infiltrationNum;
942 1 : auto &thisInfiltration = state.dataHeatBal->Infiltration(infiltrationNum);
943 1 : thisInfiltration.Name = thisInfiltrationInput.names(Item1);
944 1 : thisInfiltration.spaceIndex = thisInfiltrationInput.spaceNums(Item1);
945 1 : auto &thisSpace = state.dataHeatBal->space(thisInfiltration.spaceIndex);
946 1 : thisInfiltration.ZonePtr = thisSpace.zoneNum;
947 1 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
948 :
949 1 : thisInfiltration.ModelType = DataHeatBalance::InfiltrationModelType::ShermanGrimsrud;
950 :
951 1 : if (lAlphaFieldBlanks(3)) {
952 0 : thisInfiltration.sched = Sched::GetScheduleAlwaysOn(state); // Not an availability schedule but defaults to constant 1.0
953 1 : } else if ((thisInfiltration.sched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
954 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
955 0 : ErrorsFound = true;
956 : }
957 1 : thisInfiltration.BasicStackCoefficient = rNumericArgs(2);
958 1 : thisInfiltration.BasicWindCoefficient = rNumericArgs(3);
959 :
960 1 : if (lNumericFieldBlanks(1)) {
961 0 : ShowWarningError(state,
962 0 : format("{}{}=\"{}\", field {} is blank. 0 Infiltration will result.",
963 : RoutineName,
964 : cCurrentModuleObject,
965 0 : thisInfiltrationInput.Name,
966 : cNumericFieldNames(1)));
967 : } else {
968 1 : Real64 spaceFrac = 1.0;
969 1 : if (!thisInfiltrationInput.spaceListActive && (thisInfiltrationInput.numOfSpaces > 1)) {
970 0 : Real64 const zoneExteriorTotalSurfArea = thisZone.ExteriorTotalSurfArea;
971 0 : if (zoneExteriorTotalSurfArea > 0.0) {
972 0 : spaceFrac = thisSpace.ExteriorTotalSurfArea / zoneExteriorTotalSurfArea;
973 : } else {
974 0 : ShowSevereError(state,
975 0 : format("{}Zone exterior surface area is zero when allocating Infiltration to Spaces.", RoutineName));
976 0 : ShowContinueError(
977 : state,
978 0 : format("Occurs for {}=\"{}\" in Zone=\"{}\".", cCurrentModuleObject, thisInfiltrationInput.Name, thisZone.Name));
979 0 : ErrorsFound = true;
980 : }
981 : }
982 :
983 1 : thisInfiltration.LeakageArea = rNumericArgs(1) * spaceFrac;
984 : }
985 : // check if space has exterior surfaces
986 1 : if (thisInfiltration.spaceIndex > 0) {
987 1 : if (thisSpace.ExteriorTotalSurfArea <= 0.0) {
988 2 : ShowWarningError(state,
989 2 : format(R"({}{}="{}", Space="{}" does not have surfaces exposed to outdoors.)",
990 : RoutineName,
991 : cCurrentModuleObject,
992 1 : thisInfiltrationInput.Name,
993 1 : thisSpace.Name));
994 3 : ShowContinueError(state, "Infiltration model is appropriate for exterior spaces not interior spaces, simulation continues.");
995 : }
996 : }
997 : }
998 : }
999 : }
1000 :
1001 120 : if (totFlowCoefficientInfiltration > 0) {
1002 1 : cCurrentModuleObject = "ZoneInfiltration:FlowCoefficient";
1003 2 : for (int infilInputNum = 1; infilInputNum <= numFlowCoefficientInfiltrationObjects; ++infilInputNum) {
1004 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1005 : cCurrentModuleObject,
1006 : infilInputNum,
1007 : cAlphaArgs,
1008 : NumAlpha,
1009 : rNumericArgs,
1010 : NumNumber,
1011 : IOStat,
1012 : lNumericFieldBlanks,
1013 : lAlphaFieldBlanks,
1014 : cAlphaFieldNames,
1015 : cNumericFieldNames);
1016 :
1017 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1018 :
1019 : // Create one Infiltration instance for every space associated with this input object
1020 1 : auto &thisInfiltrationInput = infiltrationFlowCoefficientObjects(infilInputNum);
1021 2 : for (int Item1 = 1; Item1 <= thisInfiltrationInput.numOfSpaces; ++Item1) {
1022 1 : ++infiltrationNum;
1023 1 : auto &thisInfiltration = state.dataHeatBal->Infiltration(infiltrationNum);
1024 1 : thisInfiltration.Name = thisInfiltrationInput.names(Item1);
1025 1 : thisInfiltration.spaceIndex = thisInfiltrationInput.spaceNums(Item1);
1026 1 : auto &thisSpace = state.dataHeatBal->space(thisInfiltration.spaceIndex);
1027 1 : thisInfiltration.ZonePtr = thisSpace.zoneNum;
1028 1 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
1029 :
1030 1 : thisInfiltration.ModelType = DataHeatBalance::InfiltrationModelType::AIM2;
1031 :
1032 1 : if (lAlphaFieldBlanks(3)) {
1033 0 : thisInfiltration.sched = Sched::GetScheduleAlwaysOn(state); // Not an availability schedule, but defaults to constant-1.0
1034 1 : } else if ((thisInfiltration.sched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1035 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1036 0 : ErrorsFound = true;
1037 : }
1038 1 : thisInfiltration.AIM2StackCoefficient = rNumericArgs(2);
1039 1 : thisInfiltration.PressureExponent = rNumericArgs(3);
1040 1 : thisInfiltration.AIM2WindCoefficient = rNumericArgs(4);
1041 1 : thisInfiltration.ShelterFactor = rNumericArgs(5);
1042 :
1043 1 : if (lNumericFieldBlanks(1)) {
1044 0 : ShowWarningError(state,
1045 0 : format("{}{}=\"{}\", field {} is blank. 0 Infiltration will result.",
1046 : RoutineName,
1047 : cCurrentModuleObject,
1048 0 : thisInfiltrationInput.Name,
1049 : cNumericFieldNames(1)));
1050 : } else {
1051 1 : Real64 spaceFrac = 1.0;
1052 1 : if (!thisInfiltrationInput.spaceListActive && (thisInfiltrationInput.numOfSpaces > 1)) {
1053 0 : Real64 const zoneExteriorTotalSurfArea = thisZone.ExteriorTotalSurfArea;
1054 0 : if (zoneExteriorTotalSurfArea > 0.0) {
1055 0 : spaceFrac = thisSpace.ExteriorTotalSurfArea / zoneExteriorTotalSurfArea;
1056 : } else {
1057 0 : ShowSevereError(state,
1058 0 : format("{}Zone exterior surface area is zero when allocating Infiltration to Spaces.", RoutineName));
1059 0 : ShowContinueError(
1060 : state,
1061 0 : format("Occurs for {}=\"{}\" in Zone=\"{}\".", cCurrentModuleObject, thisInfiltrationInput.Name, thisZone.Name));
1062 0 : ErrorsFound = true;
1063 : }
1064 : }
1065 :
1066 1 : thisInfiltration.FlowCoefficient = rNumericArgs(1) * spaceFrac;
1067 : // check if space has exterior surfaces
1068 1 : if (thisInfiltration.spaceIndex > 0) {
1069 1 : if (thisSpace.ExteriorTotalSurfArea <= 0.0) {
1070 2 : ShowWarningError(state,
1071 2 : format(R"({}{}="{}", Space="{}" does not have surfaces exposed to outdoors.)",
1072 : RoutineName,
1073 : cCurrentModuleObject,
1074 1 : thisInfiltrationInput.Name,
1075 1 : thisSpace.Name));
1076 3 : ShowContinueError(state,
1077 : "Infiltration model is appropriate for exterior spaces not interior spaces, simulation continues.");
1078 : }
1079 : }
1080 : }
1081 : }
1082 : }
1083 : }
1084 :
1085 : // setup zone-level infiltration reports
1086 171 : for (int Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
1087 102 : if (state.dataHeatBal->Infiltration(Loop).ZonePtr > 0 &&
1088 51 : !state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).zoneOAQuadratureSum) {
1089 : // Object report variables
1090 102 : SetupOutputVariable(state,
1091 : "Infiltration Sensible Heat Loss Energy",
1092 : Constant::Units::J,
1093 51 : state.dataHeatBal->Infiltration(Loop).InfilHeatLoss,
1094 : OutputProcessor::TimeStepType::System,
1095 : OutputProcessor::StoreType::Sum,
1096 51 : state.dataHeatBal->Infiltration(Loop).Name);
1097 102 : SetupOutputVariable(state,
1098 : "Infiltration Sensible Heat Gain Energy",
1099 : Constant::Units::J,
1100 51 : state.dataHeatBal->Infiltration(Loop).InfilHeatGain,
1101 : OutputProcessor::TimeStepType::System,
1102 : OutputProcessor::StoreType::Sum,
1103 51 : state.dataHeatBal->Infiltration(Loop).Name);
1104 102 : SetupOutputVariable(state,
1105 : "Infiltration Latent Heat Loss Energy",
1106 : Constant::Units::J,
1107 51 : state.dataHeatBal->Infiltration(Loop).InfilLatentLoss,
1108 : OutputProcessor::TimeStepType::System,
1109 : OutputProcessor::StoreType::Sum,
1110 51 : state.dataHeatBal->Infiltration(Loop).Name);
1111 102 : SetupOutputVariable(state,
1112 : "Infiltration Latent Heat Gain Energy",
1113 : Constant::Units::J,
1114 51 : state.dataHeatBal->Infiltration(Loop).InfilLatentGain,
1115 : OutputProcessor::TimeStepType::System,
1116 : OutputProcessor::StoreType::Sum,
1117 51 : state.dataHeatBal->Infiltration(Loop).Name);
1118 102 : SetupOutputVariable(state,
1119 : "Infiltration Total Heat Loss Energy",
1120 : Constant::Units::J,
1121 51 : state.dataHeatBal->Infiltration(Loop).InfilTotalLoss,
1122 : OutputProcessor::TimeStepType::System,
1123 : OutputProcessor::StoreType::Sum,
1124 51 : state.dataHeatBal->Infiltration(Loop).Name);
1125 102 : SetupOutputVariable(state,
1126 : "Infiltration Total Heat Gain Energy",
1127 : Constant::Units::J,
1128 51 : state.dataHeatBal->Infiltration(Loop).InfilTotalGain,
1129 : OutputProcessor::TimeStepType::System,
1130 : OutputProcessor::StoreType::Sum,
1131 51 : state.dataHeatBal->Infiltration(Loop).Name);
1132 102 : SetupOutputVariable(state,
1133 : "Infiltration Current Density Volume Flow Rate",
1134 : Constant::Units::m3_s,
1135 51 : state.dataHeatBal->Infiltration(Loop).InfilVdotCurDensity,
1136 : OutputProcessor::TimeStepType::System,
1137 : OutputProcessor::StoreType::Average,
1138 51 : state.dataHeatBal->Infiltration(Loop).Name);
1139 102 : SetupOutputVariable(state,
1140 : "Infiltration Standard Density Volume Flow Rate",
1141 : Constant::Units::m3_s,
1142 51 : state.dataHeatBal->Infiltration(Loop).InfilVdotStdDensity,
1143 : OutputProcessor::TimeStepType::System,
1144 : OutputProcessor::StoreType::Average,
1145 51 : state.dataHeatBal->Infiltration(Loop).Name);
1146 102 : SetupOutputVariable(state,
1147 : "Infiltration Outdoor Density Volume Flow Rate",
1148 : Constant::Units::m3_s,
1149 51 : state.dataHeatBal->Infiltration(Loop).InfilVdotOutDensity,
1150 : OutputProcessor::TimeStepType::System,
1151 : OutputProcessor::StoreType::Average,
1152 51 : state.dataHeatBal->Infiltration(Loop).Name);
1153 102 : SetupOutputVariable(state,
1154 : "Infiltration Current Density Volume",
1155 : Constant::Units::m3,
1156 51 : state.dataHeatBal->Infiltration(Loop).InfilVolumeCurDensity,
1157 : OutputProcessor::TimeStepType::System,
1158 : OutputProcessor::StoreType::Sum,
1159 51 : state.dataHeatBal->Infiltration(Loop).Name);
1160 102 : SetupOutputVariable(state,
1161 : "Infiltration Standard Density Volume",
1162 : Constant::Units::m3,
1163 51 : state.dataHeatBal->Infiltration(Loop).InfilVolumeStdDensity,
1164 : OutputProcessor::TimeStepType::System,
1165 : OutputProcessor::StoreType::Sum,
1166 51 : state.dataHeatBal->Infiltration(Loop).Name);
1167 102 : SetupOutputVariable(state,
1168 : "Infiltration Mass",
1169 : Constant::Units::kg,
1170 51 : state.dataHeatBal->Infiltration(Loop).InfilMass,
1171 : OutputProcessor::TimeStepType::System,
1172 : OutputProcessor::StoreType::Sum,
1173 51 : state.dataHeatBal->Infiltration(Loop).Name);
1174 102 : SetupOutputVariable(state,
1175 : "Infiltration Mass Flow Rate",
1176 : Constant::Units::kg_s,
1177 51 : state.dataHeatBal->Infiltration(Loop).InfilMdot,
1178 : OutputProcessor::TimeStepType::System,
1179 : OutputProcessor::StoreType::Average,
1180 51 : state.dataHeatBal->Infiltration(Loop).Name);
1181 102 : SetupOutputVariable(state,
1182 : "Infiltration Current Density Air Change Rate",
1183 : Constant::Units::ach,
1184 51 : state.dataHeatBal->Infiltration(Loop).InfilAirChangeRateCurDensity,
1185 : OutputProcessor::TimeStepType::System,
1186 : OutputProcessor::StoreType::Average,
1187 51 : state.dataHeatBal->Infiltration(Loop).Name);
1188 102 : SetupOutputVariable(state,
1189 : "Infiltration Standard Density Air Change Rate",
1190 : Constant::Units::ach,
1191 51 : state.dataHeatBal->Infiltration(Loop).InfilAirChangeRateStdDensity,
1192 : OutputProcessor::TimeStepType::System,
1193 : OutputProcessor::StoreType::Average,
1194 51 : state.dataHeatBal->Infiltration(Loop).Name);
1195 102 : SetupOutputVariable(state,
1196 : "Infiltration Outdoor Density Air Change Rate",
1197 : Constant::Units::ach,
1198 51 : state.dataHeatBal->Infiltration(Loop).InfilAirChangeRateOutDensity,
1199 : OutputProcessor::TimeStepType::System,
1200 : OutputProcessor::StoreType::Average,
1201 51 : state.dataHeatBal->Infiltration(Loop).Name);
1202 :
1203 51 : if (RepVarSet(state.dataHeatBal->Infiltration(Loop).ZonePtr)) {
1204 42 : RepVarSet(state.dataHeatBal->Infiltration(Loop).ZonePtr) = false;
1205 84 : SetupOutputVariable(state,
1206 : "Zone Infiltration Sensible Heat Loss Energy",
1207 : Constant::Units::J,
1208 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilHeatLoss,
1209 : OutputProcessor::TimeStepType::System,
1210 : OutputProcessor::StoreType::Sum,
1211 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1212 84 : SetupOutputVariable(state,
1213 : "Zone Infiltration Sensible Heat Gain Energy",
1214 : Constant::Units::J,
1215 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilHeatGain,
1216 : OutputProcessor::TimeStepType::System,
1217 : OutputProcessor::StoreType::Sum,
1218 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1219 84 : SetupOutputVariable(state,
1220 : "Zone Infiltration Latent Heat Loss Energy",
1221 : Constant::Units::J,
1222 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilLatentLoss,
1223 : OutputProcessor::TimeStepType::System,
1224 : OutputProcessor::StoreType::Sum,
1225 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1226 84 : SetupOutputVariable(state,
1227 : "Zone Infiltration Latent Heat Gain Energy",
1228 : Constant::Units::J,
1229 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilLatentGain,
1230 : OutputProcessor::TimeStepType::System,
1231 : OutputProcessor::StoreType::Sum,
1232 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1233 84 : SetupOutputVariable(state,
1234 : "Zone Infiltration Total Heat Loss Energy",
1235 : Constant::Units::J,
1236 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilTotalLoss,
1237 : OutputProcessor::TimeStepType::System,
1238 : OutputProcessor::StoreType::Sum,
1239 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1240 84 : SetupOutputVariable(state,
1241 : "Zone Infiltration Total Heat Gain Energy",
1242 : Constant::Units::J,
1243 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilTotalGain,
1244 : OutputProcessor::TimeStepType::System,
1245 : OutputProcessor::StoreType::Sum,
1246 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1247 84 : SetupOutputVariable(state,
1248 : "Zone Infiltration Current Density Volume Flow Rate",
1249 : Constant::Units::m3_s,
1250 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilVdotCurDensity,
1251 : OutputProcessor::TimeStepType::System,
1252 : OutputProcessor::StoreType::Average,
1253 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1254 84 : SetupOutputVariable(state,
1255 : "Zone Infiltration Standard Density Volume Flow Rate",
1256 : Constant::Units::m3_s,
1257 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilVdotStdDensity,
1258 : OutputProcessor::TimeStepType::System,
1259 : OutputProcessor::StoreType::Average,
1260 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1261 84 : SetupOutputVariable(state,
1262 : "Zone Infiltration Outdoor Density Volume Flow Rate",
1263 : Constant::Units::m3_s,
1264 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilVdotOutDensity,
1265 : OutputProcessor::TimeStepType::System,
1266 : OutputProcessor::StoreType::Average,
1267 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1268 84 : SetupOutputVariable(state,
1269 : "Zone Infiltration Current Density Volume",
1270 : Constant::Units::m3,
1271 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilVolumeCurDensity,
1272 : OutputProcessor::TimeStepType::System,
1273 : OutputProcessor::StoreType::Sum,
1274 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1275 84 : SetupOutputVariable(state,
1276 : "Zone Infiltration Standard Density Volume",
1277 : Constant::Units::m3,
1278 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilVolumeStdDensity,
1279 : OutputProcessor::TimeStepType::System,
1280 : OutputProcessor::StoreType::Sum,
1281 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1282 84 : SetupOutputVariable(state,
1283 : "Zone Infiltration Mass",
1284 : Constant::Units::kg,
1285 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilMass,
1286 : OutputProcessor::TimeStepType::System,
1287 : OutputProcessor::StoreType::Sum,
1288 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1289 84 : SetupOutputVariable(state,
1290 : "Zone Infiltration Mass Flow Rate",
1291 : Constant::Units::kg_s,
1292 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilMdot,
1293 : OutputProcessor::TimeStepType::System,
1294 : OutputProcessor::StoreType::Average,
1295 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1296 84 : SetupOutputVariable(state,
1297 : "Zone Infiltration Current Density Air Change Rate",
1298 : Constant::Units::ach,
1299 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilAirChangeRateCurDensity,
1300 : OutputProcessor::TimeStepType::System,
1301 : OutputProcessor::StoreType::Average,
1302 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1303 84 : SetupOutputVariable(state,
1304 : "Zone Infiltration Standard Density Air Change Rate",
1305 : Constant::Units::ach,
1306 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilAirChangeRateStdDensity,
1307 : OutputProcessor::TimeStepType::System,
1308 : OutputProcessor::StoreType::Average,
1309 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1310 84 : SetupOutputVariable(state,
1311 : "Zone Infiltration Outdoor Density Air Change Rate",
1312 : Constant::Units::ach,
1313 42 : state.dataHeatBal->ZnAirRpt(state.dataHeatBal->Infiltration(Loop).ZonePtr).InfilAirChangeRateOutDensity,
1314 : OutputProcessor::TimeStepType::System,
1315 : OutputProcessor::StoreType::Average,
1316 42 : state.dataHeatBal->Zone(state.dataHeatBal->Infiltration(Loop).ZonePtr).Name);
1317 : }
1318 : }
1319 :
1320 51 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1321 0 : SetupEMSActuator(state,
1322 : "Zone Infiltration",
1323 0 : state.dataHeatBal->Infiltration(Loop).Name,
1324 : "Air Exchange Flow Rate",
1325 : "[m3/s]",
1326 0 : state.dataHeatBal->Infiltration(Loop).EMSOverrideOn,
1327 0 : state.dataHeatBal->Infiltration(Loop).EMSAirFlowRateValue);
1328 : }
1329 : }
1330 :
1331 : // Set up and process ZoneVentilation:* inputs
1332 :
1333 120 : RepVarSet = true;
1334 :
1335 120 : cCurrentModuleObject = "ZoneVentilation:DesignFlowRate";
1336 120 : int numDesignFlowVentilationObjects = 0;
1337 120 : int totDesignFlowVentilation = 0; // Total ZoneVentilation:DesignFlowRate instances after expansion to spaces
1338 240 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> ventilationDesignFlowRateObjects;
1339 120 : InternalHeatGains::setupIHGZonesAndSpaces(
1340 : state, cCurrentModuleObject, ventilationDesignFlowRateObjects, numDesignFlowVentilationObjects, totDesignFlowVentilation, ErrorsFound);
1341 :
1342 120 : cCurrentModuleObject = "ZoneVentilation:WindandStackOpenArea";
1343 120 : int numWindStackVentilationObjects = 0;
1344 120 : int totWindStackVentilation = 0; // Total ZoneVentilation:WindandStackOpenArea instances after expansion to spaces
1345 240 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> ventilationWindStackObjects;
1346 120 : InternalHeatGains::setupIHGZonesAndSpaces(state,
1347 : cCurrentModuleObject,
1348 : ventilationWindStackObjects,
1349 : numWindStackVentilationObjects,
1350 : totWindStackVentilation,
1351 : ErrorsFound,
1352 : zoneListNotAllowed);
1353 :
1354 120 : state.dataHeatBal->TotVentilation = totDesignFlowVentilation + totWindStackVentilation;
1355 120 : state.dataHeatBal->Ventilation.allocate(state.dataHeatBal->TotVentilation);
1356 :
1357 120 : int ventilationNum = 0;
1358 120 : if (numDesignFlowVentilationObjects > 0) {
1359 1 : cCurrentModuleObject = "ZoneVentilation:DesignFlowRate";
1360 7 : for (int ventInputNum = 1; ventInputNum <= numDesignFlowVentilationObjects; ++ventInputNum) {
1361 :
1362 6 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1363 : cCurrentModuleObject,
1364 : ventInputNum,
1365 : cAlphaArgs,
1366 : NumAlpha,
1367 : rNumericArgs,
1368 : NumNumber,
1369 : IOStat,
1370 : lNumericFieldBlanks,
1371 : lAlphaFieldBlanks,
1372 : cAlphaFieldNames,
1373 : cNumericFieldNames);
1374 :
1375 6 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1376 6 : auto &thisVentilationInput = ventilationDesignFlowRateObjects(ventInputNum);
1377 16 : for (int Item1 = 1; Item1 <= thisVentilationInput.numOfSpaces; ++Item1) {
1378 10 : ++ventilationNum;
1379 10 : auto &thisVentilation = state.dataHeatBal->Ventilation(ventilationNum);
1380 10 : thisVentilation.Name = thisVentilationInput.names(Item1);
1381 10 : thisVentilation.spaceIndex = thisVentilationInput.spaceNums(Item1);
1382 10 : auto &thisSpace = state.dataHeatBal->space(thisVentilation.spaceIndex);
1383 10 : thisVentilation.ZonePtr = thisSpace.zoneNum;
1384 10 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
1385 :
1386 10 : thisVentilation.ModelType = DataHeatBalance::VentilationModelType::DesignFlowRate;
1387 10 : if (lAlphaFieldBlanks(3)) {
1388 10 : thisVentilation.availSched = Sched::GetScheduleAlwaysOn(state); // Defaults to constant-1.0
1389 0 : } else if ((thisVentilation.availSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1390 0 : if (Item1 == 1) {
1391 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1392 0 : ErrorsFound = true;
1393 : }
1394 : }
1395 :
1396 : // Ventilation equipment design level calculation method
1397 10 : AirflowSpec flow = static_cast<AirflowSpec>(getEnumValue(airflowSpecNamesUC, cAlphaArgs(4))); // NOLINT(modernize-use-auto)
1398 10 : switch (flow) {
1399 0 : case AirflowSpec::FlowPerZone:
1400 0 : thisVentilation.DesignLevel = rNumericArgs(1);
1401 0 : if (lNumericFieldBlanks(1)) {
1402 0 : ShowWarningError(state,
1403 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Ventilation will result.",
1404 : RoutineName,
1405 : cCurrentModuleObject,
1406 0 : thisVentilation.Name,
1407 : cAlphaFieldNames(4),
1408 : cNumericFieldNames(1)));
1409 : }
1410 0 : break;
1411 :
1412 10 : case AirflowSpec::FlowPerArea:
1413 10 : if (thisVentilation.spaceIndex != 0) {
1414 10 : if (rNumericArgs(2) >= 0.0) {
1415 10 : thisVentilation.DesignLevel = rNumericArgs(2) * thisSpace.FloorArea;
1416 10 : if (thisSpace.FloorArea <= 0.0) {
1417 0 : ShowWarningError(state,
1418 0 : format("{}{}=\"{}\", {} specifies {}, but Space Floor Area = 0. 0 Ventilation will result.",
1419 : RoutineName,
1420 : cCurrentModuleObject,
1421 0 : thisVentilation.Name,
1422 : cAlphaFieldNames(4),
1423 : cNumericFieldNames(2)));
1424 : }
1425 : } else {
1426 0 : ShowSevereError(state,
1427 0 : format("{}{}=\"{}\", invalid flow/area specification [<0.0]={:.3R}",
1428 : RoutineName,
1429 : cCurrentModuleObject,
1430 0 : thisVentilation.Name,
1431 : rNumericArgs(2)));
1432 0 : ErrorsFound = true;
1433 : }
1434 : }
1435 10 : if (lNumericFieldBlanks(2)) {
1436 0 : ShowWarningError(state,
1437 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Ventilation will result.",
1438 : RoutineName,
1439 : cCurrentModuleObject,
1440 0 : thisVentilation.Name,
1441 : cAlphaFieldNames(4),
1442 : cNumericFieldNames(2)));
1443 : }
1444 10 : break;
1445 :
1446 0 : case AirflowSpec::FlowPerPerson:
1447 0 : if (thisVentilation.spaceIndex != 0) {
1448 0 : if (rNumericArgs(3) >= 0.0) {
1449 0 : thisVentilation.DesignLevel = rNumericArgs(3) * thisSpace.TotOccupants;
1450 0 : if (thisSpace.TotOccupants <= 0.0) {
1451 0 : ShowWarningError(state,
1452 0 : format("{}{}=\"{}\", {} specifies {}, but Zone Total Occupants = 0. 0 Ventilation will result.",
1453 : RoutineName,
1454 : cCurrentModuleObject,
1455 0 : thisVentilation.Name,
1456 : cAlphaFieldNames(4),
1457 : cNumericFieldNames(3)));
1458 : }
1459 : } else {
1460 0 : ShowSevereError(state,
1461 0 : format("{}{}=\"{}\", invalid flow/person specification [<0.0]={:.3R}",
1462 : RoutineName,
1463 : cCurrentModuleObject,
1464 0 : thisVentilation.Name,
1465 : rNumericArgs(3)));
1466 0 : ErrorsFound = true;
1467 : }
1468 : }
1469 0 : if (lNumericFieldBlanks(3)) {
1470 0 : ShowWarningError(state,
1471 0 : format("{}{}=\"{}\", {}specifies {}, but that field is blank. 0 Ventilation will result.",
1472 : RoutineName,
1473 : cCurrentModuleObject,
1474 0 : thisVentilation.Name,
1475 : cAlphaFieldNames(4),
1476 : cNumericFieldNames(3)));
1477 : }
1478 0 : break;
1479 :
1480 0 : case AirflowSpec::AirChanges:
1481 0 : if (thisVentilation.spaceIndex != 0) {
1482 0 : if (rNumericArgs(4) >= 0.0) {
1483 0 : thisVentilation.DesignLevel = rNumericArgs(4) * thisSpace.Volume / Constant::rSecsInHour;
1484 0 : if (thisSpace.Volume <= 0.0) {
1485 0 : ShowWarningError(state,
1486 0 : format("{}{}=\"{}\", {} specifies {}, but Space Volume = 0. 0 Ventilation will result.",
1487 : RoutineName,
1488 : cCurrentModuleObject,
1489 0 : thisVentilation.Name,
1490 : cAlphaFieldNames(4),
1491 : cNumericFieldNames(4)));
1492 : }
1493 : } else {
1494 0 : ShowSevereError(state,
1495 0 : format("{}{}=\"{}\", invalid ACH (air changes per hour) specification [<0.0]={:.3R}",
1496 : RoutineName,
1497 : cCurrentModuleObject,
1498 0 : thisVentilation.Name,
1499 : rNumericArgs(5)));
1500 0 : ErrorsFound = true;
1501 : }
1502 : }
1503 0 : if (lNumericFieldBlanks(4)) {
1504 0 : ShowWarningError(state,
1505 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Ventilation will result.",
1506 : RoutineName,
1507 : cCurrentModuleObject,
1508 0 : thisVentilation.Name,
1509 : cAlphaFieldNames(4),
1510 : cNumericFieldNames(4)));
1511 : }
1512 0 : break;
1513 :
1514 0 : default:
1515 0 : if (Item1 == 1) {
1516 0 : ShowSevereError(
1517 : state,
1518 0 : format("{}{}=\"{}\", invalid calculation method={}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(4)));
1519 0 : ErrorsFound = true;
1520 : }
1521 : }
1522 :
1523 10 : if (cAlphaArgs(5).empty()) {
1524 0 : thisVentilation.FanType = DataHeatBalance::VentilationType::Natural;
1525 : } else {
1526 10 : thisVentilation.FanType = static_cast<DataHeatBalance::VentilationType>(getEnumValue(ventilationTypeNamesUC, cAlphaArgs(5)));
1527 10 : if (thisVentilation.FanType == DataHeatBalance::VentilationType::Invalid) {
1528 0 : ShowSevereError(state,
1529 0 : format(R"({}{}="{}". invalid {}="{}".)",
1530 : RoutineName,
1531 : cCurrentModuleObject,
1532 0 : thisVentilation.Name,
1533 : cAlphaFieldNames(5),
1534 : cAlphaArgs(5)));
1535 0 : ErrorsFound = true;
1536 : }
1537 : }
1538 :
1539 10 : thisVentilation.FanPressure = rNumericArgs(5);
1540 10 : if (thisVentilation.FanPressure < 0.0) {
1541 0 : if (Item1 == 1) {
1542 0 : ShowSevereError(
1543 : state,
1544 0 : format("{}{}=\"{}\", {} must be >=0", RoutineName, cCurrentModuleObject, thisVentilation.Name, cNumericFieldNames(5)));
1545 0 : ErrorsFound = true;
1546 : }
1547 : }
1548 :
1549 10 : thisVentilation.FanEfficiency = rNumericArgs(6);
1550 10 : if ((thisVentilation.FanEfficiency <= 0.0) || (thisVentilation.FanEfficiency > 1.0)) {
1551 0 : if (Item1 == 1) {
1552 0 : ShowSevereError(state,
1553 0 : format("{}{}=\"{}\",{} must be in range >0 and <= 1",
1554 : RoutineName,
1555 : cCurrentModuleObject,
1556 0 : thisVentilation.Name,
1557 : cNumericFieldNames(6)));
1558 0 : ErrorsFound = true;
1559 : }
1560 : }
1561 :
1562 : // Override any user input for cases where natural ventilation is being used
1563 10 : if (thisVentilation.FanType == DataHeatBalance::VentilationType::Natural) {
1564 10 : thisVentilation.FanPressure = 0.0;
1565 10 : thisVentilation.FanEfficiency = 1.0;
1566 : }
1567 :
1568 10 : thisVentilation.ConstantTermCoef = !lNumericFieldBlanks(7) ? rNumericArgs(7) : 1.0;
1569 10 : thisVentilation.TemperatureTermCoef = !lNumericFieldBlanks(8) ? rNumericArgs(8) : 0.0;
1570 10 : thisVentilation.VelocityTermCoef = !lNumericFieldBlanks(9) ? rNumericArgs(9) : 0.0;
1571 10 : thisVentilation.VelocitySQTermCoef = !lNumericFieldBlanks(10) ? rNumericArgs(10) : 0.0;
1572 :
1573 10 : if (thisVentilation.ConstantTermCoef == 0.0 && thisVentilation.TemperatureTermCoef == 0.0 &&
1574 0 : thisVentilation.VelocityTermCoef == 0.0 && thisVentilation.VelocitySQTermCoef == 0.0) {
1575 0 : if (Item1 == 1) {
1576 0 : ShowWarningError(
1577 : state,
1578 0 : format(
1579 : "{}{}=\"{}\", in {}=\"{}\".", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaFieldNames(2), cAlphaArgs(2)));
1580 0 : ShowContinueError(state, "Ventilation Coefficients are all zero. No Ventilation will be reported.");
1581 : }
1582 : }
1583 :
1584 10 : if (!lNumericFieldBlanks(11)) {
1585 0 : thisVentilation.MinIndoorTemperature = rNumericArgs(11);
1586 : } else {
1587 10 : thisVentilation.MinIndoorTemperature = -VentilTempLimit;
1588 : }
1589 :
1590 : // Ventilation(Loop)%MinIndoorTemperature = rNumericArgs(11)
1591 10 : if ((thisVentilation.MinIndoorTemperature < -VentilTempLimit) || (thisVentilation.MinIndoorTemperature > VentilTempLimit)) {
1592 0 : if (Item1 == 1) {
1593 0 : ShowSevereError(state,
1594 0 : format("{}{}=\"{}\" must have {} between -100C and 100C.",
1595 : RoutineName,
1596 : cCurrentModuleObject,
1597 : cAlphaArgs(1),
1598 : cNumericFieldNames(11)));
1599 0 : ShowContinueError(state, format("...value entered=[{:.2R}].", rNumericArgs(11)));
1600 0 : ErrorsFound = true;
1601 : }
1602 : }
1603 :
1604 10 : if (!lAlphaFieldBlanks(6)) {
1605 0 : thisVentilation.minIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(6));
1606 : }
1607 :
1608 10 : if (Item1 == 1) { // Item check prevents this error from printing multiple times
1609 6 : if (lAlphaFieldBlanks(6)) {
1610 6 : if (lNumericFieldBlanks(11)) {
1611 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(11), format("The default value will be used ({:.1R})",
1612 : // -VentilTempLimit));
1613 : }
1614 0 : } else if (thisVentilation.minIndoorTempSched == nullptr) {
1615 0 : ShowWarningItemNotFound(state,
1616 : eoh,
1617 0 : cAlphaFieldNames(6),
1618 0 : cAlphaArgs(6),
1619 0 : format("The default value will be used ({:.1R})", thisVentilation.MinIndoorTemperature));
1620 0 : } else if (!thisVentilation.minIndoorTempSched->checkMinMaxVals(
1621 : state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
1622 0 : Sched::ShowSevereBadMinMax(
1623 0 : state, eoh, cAlphaFieldNames(6), cAlphaArgs(6), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
1624 0 : ErrorsFound = true;
1625 0 : } else if (!lNumericFieldBlanks(11)) {
1626 0 : ShowWarningCustom(
1627 : state,
1628 : eoh,
1629 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(6), cAlphaFieldNames(11), cAlphaFieldNames(6)));
1630 : }
1631 : }
1632 :
1633 10 : thisVentilation.MaxIndoorTemperature = !lNumericFieldBlanks(12) ? rNumericArgs(12) : VentilTempLimit;
1634 10 : if ((thisVentilation.MaxIndoorTemperature < -VentilTempLimit) || (thisVentilation.MaxIndoorTemperature > VentilTempLimit)) {
1635 0 : if (Item1 == 1) {
1636 0 : ShowSevereError(state,
1637 0 : format("{}{} = {} must have a maximum indoor temperature between -100C and 100C",
1638 : RoutineName,
1639 : cCurrentModuleObject,
1640 : cAlphaArgs(1)));
1641 0 : ErrorsFound = true;
1642 : }
1643 : }
1644 :
1645 10 : if (!lAlphaFieldBlanks(7)) {
1646 0 : thisVentilation.maxIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(7));
1647 : }
1648 :
1649 10 : if (Item1 == 1) { // Item check prevents this error from printing multiple times
1650 6 : if (lAlphaFieldBlanks(7)) {
1651 6 : if (lNumericFieldBlanks(12)) {
1652 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(12), format("The default value will be used ({:.1R})",
1653 : // VentilTempLimit));
1654 : }
1655 0 : } else if (thisVentilation.maxIndoorTempSched == nullptr) {
1656 0 : ShowWarningItemNotFound(state,
1657 : eoh,
1658 0 : cAlphaFieldNames(7),
1659 0 : cAlphaArgs(7),
1660 0 : format("The default value will be used ({:.1R})", thisVentilation.MaxIndoorTemperature));
1661 0 : } else if (!thisVentilation.maxIndoorTempSched->checkMinMaxVals(
1662 : state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
1663 0 : Sched::ShowSevereBadMinMax(
1664 0 : state, eoh, cAlphaFieldNames(7), cAlphaArgs(7), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
1665 0 : ErrorsFound = true;
1666 0 : } else if (!lNumericFieldBlanks(12)) {
1667 0 : ShowWarningCustom(
1668 : state,
1669 : eoh,
1670 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(7), cAlphaFieldNames(12), cAlphaFieldNames(7)));
1671 : }
1672 : }
1673 :
1674 10 : thisVentilation.DelTemperature = !lNumericFieldBlanks(13) ? rNumericArgs(13) : -VentilTempLimit;
1675 : // Ventilation(Loop)%DelTemperature = rNumericArgs(13) ! 3/12/03 Negative del temp now allowed COP
1676 :
1677 10 : if (!lAlphaFieldBlanks(8)) {
1678 0 : thisVentilation.deltaTempSched = Sched::GetSchedule(state, cAlphaArgs(8));
1679 : }
1680 :
1681 10 : if (Item1 == 1) { // Item check prevents this error from printing multiple times
1682 6 : if (lAlphaFieldBlanks(8)) {
1683 6 : if (lNumericFieldBlanks(13)) {
1684 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(13), format("The default value will be used ({:.1R})",
1685 : // VentilTempLimit));
1686 : }
1687 0 : } else if (thisVentilation.deltaTempSched == nullptr) {
1688 0 : ShowWarningItemNotFound(state,
1689 : eoh,
1690 0 : cAlphaFieldNames(8),
1691 0 : cAlphaArgs(8),
1692 0 : format("The default value will be used ({:.1R})", thisVentilation.DelTemperature));
1693 0 : } else if (!thisVentilation.deltaTempSched->checkMinVal(state, Clusive::In, -VentilTempLimit)) {
1694 0 : Sched::ShowSevereBadMin(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8), Clusive::In, -100);
1695 0 : ErrorsFound = true;
1696 0 : } else if (!lNumericFieldBlanks(13)) {
1697 0 : ShowWarningCustom(
1698 : state,
1699 : eoh,
1700 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(8), cAlphaFieldNames(13), cAlphaFieldNames(8)));
1701 : }
1702 : }
1703 :
1704 10 : thisVentilation.MinOutdoorTemperature = !lNumericFieldBlanks(14) ? rNumericArgs(14) : -VentilTempLimit;
1705 10 : if ((thisVentilation.MinOutdoorTemperature < -VentilTempLimit) || (thisVentilation.MinOutdoorTemperature > VentilTempLimit)) {
1706 0 : if (Item1 == 1) {
1707 0 : ShowSevereError(state,
1708 0 : format("{}{} statement = {} must have {} between -100C and 100C",
1709 : RoutineName,
1710 : cCurrentModuleObject,
1711 : cAlphaArgs(1),
1712 : cNumericFieldNames(14)));
1713 0 : ErrorsFound = true;
1714 : }
1715 : }
1716 :
1717 10 : if (!lAlphaFieldBlanks(9)) {
1718 0 : thisVentilation.minOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(9));
1719 : }
1720 :
1721 10 : if (Item1 == 1) { // Item check prevents this error from printing multiple times
1722 6 : if (lAlphaFieldBlanks(9)) {
1723 6 : if (lNumericFieldBlanks(14)) {
1724 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(14), format("The default value will be used ({:.1R})",
1725 : // VentilTempLimit));
1726 : }
1727 0 : } else if (thisVentilation.minOutdoorTempSched == nullptr) {
1728 0 : ShowWarningItemNotFound(state,
1729 : eoh,
1730 0 : cAlphaFieldNames(9),
1731 0 : cAlphaArgs(9),
1732 0 : format("The default value will be used ({:.1R})", thisVentilation.MinOutdoorTemperature));
1733 0 : } else if (!thisVentilation.minOutdoorTempSched->checkMinMaxVals(
1734 : state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
1735 0 : Sched::ShowSevereBadMinMax(
1736 0 : state, eoh, cAlphaFieldNames(9), cAlphaArgs(9), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
1737 0 : ErrorsFound = true;
1738 0 : } else if (!lNumericFieldBlanks(14)) {
1739 0 : ShowWarningCustom(
1740 : state,
1741 : eoh,
1742 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(9), cNumericFieldNames(14), cAlphaFieldNames(9)));
1743 : }
1744 : }
1745 :
1746 10 : thisVentilation.MaxOutdoorTemperature = !lNumericFieldBlanks(15) ? rNumericArgs(15) : VentilTempLimit;
1747 10 : if (Item1 == 1) {
1748 6 : if ((thisVentilation.MaxOutdoorTemperature < -VentilTempLimit) || (thisVentilation.MaxOutdoorTemperature > VentilTempLimit)) {
1749 0 : ShowSevereError(state,
1750 0 : format("{}{} statement = {} must have a {} between -100C and 100C",
1751 : RoutineName,
1752 : cCurrentModuleObject,
1753 : cAlphaArgs(1),
1754 : cNumericFieldNames(15)));
1755 0 : ErrorsFound = true;
1756 : }
1757 : }
1758 :
1759 10 : if (!lAlphaFieldBlanks(10)) {
1760 0 : thisVentilation.maxOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(10));
1761 : }
1762 :
1763 10 : if (Item1 == 1) { // Item check prevents this error from printing multiple times
1764 6 : if (lAlphaFieldBlanks(10)) {
1765 6 : if (lNumericFieldBlanks(15)) {
1766 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(15), format("The default value will be used ({:.1R})",
1767 : // VentilTempLimit));
1768 : }
1769 0 : } else if (thisVentilation.maxOutdoorTempSched == nullptr) {
1770 0 : ShowWarningItemNotFound(state,
1771 : eoh,
1772 0 : cAlphaFieldNames(10),
1773 0 : cAlphaArgs(10),
1774 0 : format("The default value will be used ({:.1R})", thisVentilation.MaxOutdoorTemperature));
1775 0 : } else if (!thisVentilation.maxOutdoorTempSched->checkMinMaxVals(
1776 : state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
1777 0 : Sched::ShowSevereBadMinMax(
1778 0 : state, eoh, cAlphaFieldNames(10), cAlphaArgs(10), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
1779 0 : ErrorsFound = true;
1780 0 : } else if (!lNumericFieldBlanks(15)) {
1781 0 : ShowWarningCustom(
1782 : state,
1783 : eoh,
1784 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(10), cNumericFieldNames(15), cAlphaFieldNames(15)));
1785 : }
1786 : }
1787 :
1788 10 : thisVentilation.MaxWindSpeed = !lNumericFieldBlanks(16) ? rNumericArgs(16) : VentilWSLimit;
1789 10 : if (Item1 == 1) {
1790 6 : if ((thisVentilation.MaxWindSpeed < -VentilWSLimit) || (thisVentilation.MaxWindSpeed > VentilWSLimit)) {
1791 0 : ShowSevereError(state,
1792 0 : format("{}{} statement = {} must have a maximum wind speed between -40 m/s and 40 m/s",
1793 : RoutineName,
1794 : cCurrentModuleObject,
1795 : cAlphaArgs(1)));
1796 0 : ErrorsFound = true;
1797 : }
1798 : }
1799 :
1800 10 : thisVentilation.densityBasis = static_cast<DataHeatBalance::InfVentDensityBasis>(
1801 10 : getEnumValue(infVentDensityBasisNamesUC, cAlphaArgs(11))); // NOLINT(modernize-use-auto)
1802 :
1803 : // Report variables should be added for individual VENTILATION objects, in addition to zone totals below
1804 :
1805 10 : if (thisVentilation.ZonePtr > 0) {
1806 10 : if (RepVarSet(thisVentilation.ZonePtr) && !thisZone.zoneOAQuadratureSum) {
1807 2 : RepVarSet(thisVentilation.ZonePtr) = false;
1808 4 : SetupOutputVariable(state,
1809 : "Zone Ventilation Sensible Heat Loss Energy",
1810 : Constant::Units::J,
1811 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilHeatLoss,
1812 : OutputProcessor::TimeStepType::System,
1813 : OutputProcessor::StoreType::Sum,
1814 2 : thisZone.Name);
1815 4 : SetupOutputVariable(state,
1816 : "Zone Ventilation Sensible Heat Gain Energy",
1817 : Constant::Units::J,
1818 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilHeatGain,
1819 : OutputProcessor::TimeStepType::System,
1820 : OutputProcessor::StoreType::Sum,
1821 2 : thisZone.Name);
1822 4 : SetupOutputVariable(state,
1823 : "Zone Ventilation Latent Heat Loss Energy",
1824 : Constant::Units::J,
1825 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilLatentLoss,
1826 : OutputProcessor::TimeStepType::System,
1827 : OutputProcessor::StoreType::Sum,
1828 2 : thisZone.Name);
1829 4 : SetupOutputVariable(state,
1830 : "Zone Ventilation Latent Heat Gain Energy",
1831 : Constant::Units::J,
1832 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilLatentGain,
1833 : OutputProcessor::TimeStepType::System,
1834 : OutputProcessor::StoreType::Sum,
1835 2 : thisZone.Name);
1836 4 : SetupOutputVariable(state,
1837 : "Zone Ventilation Total Heat Loss Energy",
1838 : Constant::Units::J,
1839 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilTotalLoss,
1840 : OutputProcessor::TimeStepType::System,
1841 : OutputProcessor::StoreType::Sum,
1842 2 : thisZone.Name);
1843 4 : SetupOutputVariable(state,
1844 : "Zone Ventilation Total Heat Gain Energy",
1845 : Constant::Units::J,
1846 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilTotalGain,
1847 : OutputProcessor::TimeStepType::System,
1848 : OutputProcessor::StoreType::Sum,
1849 2 : thisZone.Name);
1850 4 : SetupOutputVariable(state,
1851 : "Zone Ventilation Current Density Volume Flow Rate",
1852 : Constant::Units::m3_s,
1853 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVdotCurDensity,
1854 : OutputProcessor::TimeStepType::System,
1855 : OutputProcessor::StoreType::Average,
1856 2 : thisZone.Name);
1857 4 : SetupOutputVariable(state,
1858 : "Zone Ventilation Standard Density Volume Flow Rate",
1859 : Constant::Units::m3_s,
1860 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVdotStdDensity,
1861 : OutputProcessor::TimeStepType::System,
1862 : OutputProcessor::StoreType::Average,
1863 2 : thisZone.Name);
1864 4 : SetupOutputVariable(state,
1865 : "Zone Ventilation Outdoor Density Volume Flow Rate",
1866 : Constant::Units::m3_s,
1867 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVdotOutDensity,
1868 : OutputProcessor::TimeStepType::System,
1869 : OutputProcessor::StoreType::Average,
1870 2 : thisZone.Name);
1871 4 : SetupOutputVariable(state,
1872 : "Zone Ventilation Current Density Volume",
1873 : Constant::Units::m3,
1874 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVolumeCurDensity,
1875 : OutputProcessor::TimeStepType::System,
1876 : OutputProcessor::StoreType::Sum,
1877 2 : thisZone.Name);
1878 4 : SetupOutputVariable(state,
1879 : "Zone Ventilation Standard Density Volume",
1880 : Constant::Units::m3,
1881 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVolumeStdDensity,
1882 : OutputProcessor::TimeStepType::System,
1883 : OutputProcessor::StoreType::Sum,
1884 2 : thisZone.Name);
1885 4 : SetupOutputVariable(state,
1886 : "Zone Ventilation Mass",
1887 : Constant::Units::kg,
1888 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilMass,
1889 : OutputProcessor::TimeStepType::System,
1890 : OutputProcessor::StoreType::Sum,
1891 2 : thisZone.Name);
1892 4 : SetupOutputVariable(state,
1893 : "Zone Ventilation Mass Flow Rate",
1894 : Constant::Units::kg_s,
1895 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilMdot,
1896 : OutputProcessor::TimeStepType::System,
1897 : OutputProcessor::StoreType::Average,
1898 2 : thisZone.Name);
1899 4 : SetupOutputVariable(state,
1900 : "Zone Ventilation Current Density Air Change Rate",
1901 : Constant::Units::ach,
1902 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirChangeRateCurDensity,
1903 : OutputProcessor::TimeStepType::System,
1904 : OutputProcessor::StoreType::Average,
1905 2 : thisZone.Name);
1906 4 : SetupOutputVariable(state,
1907 : "Zone Ventilation Standard Density Air Change Rate",
1908 : Constant::Units::ach,
1909 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirChangeRateStdDensity,
1910 : OutputProcessor::TimeStepType::System,
1911 : OutputProcessor::StoreType::Average,
1912 2 : thisZone.Name);
1913 4 : SetupOutputVariable(state,
1914 : "Zone Ventilation Outdoor Density Air Change Rate",
1915 : Constant::Units::ach,
1916 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirChangeRateOutDensity,
1917 : OutputProcessor::TimeStepType::System,
1918 : OutputProcessor::StoreType::Average,
1919 2 : thisZone.Name);
1920 4 : SetupOutputVariable(state,
1921 : "Zone Ventilation Fan Electricity Energy",
1922 : Constant::Units::J,
1923 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilFanElec,
1924 : OutputProcessor::TimeStepType::System,
1925 : OutputProcessor::StoreType::Sum,
1926 2 : thisZone.Name,
1927 : Constant::eResource::Electricity,
1928 : OutputProcessor::Group::Building,
1929 : OutputProcessor::EndUseCat::Fans,
1930 : "Ventilation (simple)",
1931 2 : thisZone.Name);
1932 4 : SetupOutputVariable(state,
1933 : "Zone Ventilation Air Inlet Temperature",
1934 : Constant::Units::C,
1935 2 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirTemp,
1936 : OutputProcessor::TimeStepType::System,
1937 : OutputProcessor::StoreType::Average,
1938 2 : thisZone.Name);
1939 : }
1940 : }
1941 :
1942 10 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1943 0 : SetupEMSActuator(state,
1944 : "Zone Ventilation",
1945 : thisVentilation.Name,
1946 : "Air Exchange Flow Rate",
1947 : "[m3/s]",
1948 0 : thisVentilation.EMSSimpleVentOn,
1949 0 : thisVentilation.EMSimpleVentFlowRate);
1950 : }
1951 : }
1952 : }
1953 : }
1954 :
1955 120 : if (numWindStackVentilationObjects > 0) {
1956 0 : cCurrentModuleObject = "ZoneVentilation:WindandStackOpenArea";
1957 0 : for (int ventInputNum = 1; ventInputNum <= numWindStackVentilationObjects; ++ventInputNum) {
1958 :
1959 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1960 : cCurrentModuleObject,
1961 : ventInputNum,
1962 : cAlphaArgs,
1963 : NumAlpha,
1964 : rNumericArgs,
1965 : NumNumber,
1966 : IOStat,
1967 : lNumericFieldBlanks,
1968 : lAlphaFieldBlanks,
1969 : cAlphaFieldNames,
1970 : cNumericFieldNames);
1971 :
1972 0 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1973 :
1974 0 : auto &thisVentilationInput = ventilationWindStackObjects(ventInputNum);
1975 0 : for (int Item1 = 1; Item1 <= thisVentilationInput.numOfSpaces; ++Item1) {
1976 0 : ++ventilationNum;
1977 0 : auto &thisVentilation = state.dataHeatBal->Ventilation(ventilationNum);
1978 0 : thisVentilation.Name = thisVentilationInput.names(Item1);
1979 0 : thisVentilation.spaceIndex = thisVentilationInput.spaceNums(Item1);
1980 0 : auto &thisSpace = state.dataHeatBal->space(thisVentilation.spaceIndex);
1981 0 : thisVentilation.ZonePtr = thisSpace.zoneNum;
1982 0 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
1983 :
1984 0 : thisVentilation.ModelType = DataHeatBalance::VentilationModelType::WindAndStack;
1985 :
1986 0 : thisVentilation.availSched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1987 :
1988 0 : thisVentilation.OpenArea = rNumericArgs(1);
1989 0 : if (thisVentilation.OpenArea < 0.0) {
1990 0 : ShowSevereError(
1991 0 : state, format("{}{}=\"{}\", {} must be positive.", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1)));
1992 0 : ErrorsFound = true;
1993 : }
1994 :
1995 0 : if (lAlphaFieldBlanks(3)) {
1996 0 : thisVentilation.openAreaFracSched =
1997 0 : Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
1998 0 : } else if ((thisVentilation.openAreaFracSched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
1999 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
2000 0 : ErrorsFound = true;
2001 : }
2002 :
2003 0 : thisVentilation.OpenEff = rNumericArgs(2);
2004 0 : if (thisVentilation.OpenEff != Constant::AutoCalculate && (thisVentilation.OpenEff < 0.0 || thisVentilation.OpenEff > 1.0)) {
2005 0 : ShowSevereError(
2006 : state,
2007 0 : format("{}{}=\"{}\", {} must be between 0 and 1.", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(2)));
2008 0 : ErrorsFound = true;
2009 : }
2010 :
2011 0 : thisVentilation.EffAngle = rNumericArgs(3);
2012 0 : if (thisVentilation.EffAngle < 0.0 || thisVentilation.EffAngle >= 360.0) {
2013 0 : ShowSevereError(
2014 : state,
2015 0 : format(
2016 : "{}{}=\"{}\", {} must be between 0 and 360.", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(3)));
2017 0 : ErrorsFound = true;
2018 : }
2019 :
2020 0 : thisVentilation.DH = rNumericArgs(4);
2021 0 : if (thisVentilation.DH < 0.0) {
2022 0 : ShowSevereError(
2023 0 : state, format("{}{}=\"{}\", {} must be positive.", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(4)));
2024 0 : ErrorsFound = true;
2025 : }
2026 :
2027 0 : thisVentilation.DiscCoef = rNumericArgs(5);
2028 0 : if (thisVentilation.DiscCoef != Constant::AutoCalculate && (thisVentilation.DiscCoef < 0.0 || thisVentilation.DiscCoef > 1.0)) {
2029 0 : ShowSevereError(
2030 : state,
2031 0 : format("{}{}=\"{}\", {} must be between 0 and 1.", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(5)));
2032 0 : ErrorsFound = true;
2033 : }
2034 :
2035 0 : if (!lNumericFieldBlanks(6)) {
2036 0 : thisVentilation.MinIndoorTemperature = rNumericArgs(6);
2037 : } else {
2038 0 : thisVentilation.MinIndoorTemperature = -VentilTempLimit;
2039 : }
2040 0 : if ((thisVentilation.MinIndoorTemperature < -VentilTempLimit) || (thisVentilation.MinIndoorTemperature > VentilTempLimit)) {
2041 0 : ShowSevereError(state,
2042 0 : format("{}{} statement = {} must have {} between -100C and 100C",
2043 : RoutineName,
2044 : cCurrentModuleObject,
2045 : cAlphaArgs(1),
2046 : cNumericFieldNames(6)));
2047 0 : ErrorsFound = true;
2048 : }
2049 :
2050 0 : if (!lAlphaFieldBlanks(4)) {
2051 0 : thisVentilation.minIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(4));
2052 : }
2053 :
2054 0 : if (lAlphaFieldBlanks(4)) {
2055 0 : if (lNumericFieldBlanks(6)) {
2056 : // ShowWarningEmptyField(state, eoh, cAlphaFieldNames(12), format("The default value will be used ({:.1R})",
2057 : // VentilTempLimit));
2058 : }
2059 0 : } else if (thisVentilation.minIndoorTempSched == nullptr) {
2060 0 : ShowWarningItemNotFound(state,
2061 : eoh,
2062 0 : cAlphaFieldNames(4),
2063 0 : cAlphaArgs(4),
2064 0 : format("The default value will be used ({:.1R})", thisVentilation.MinIndoorTemperature));
2065 0 : } else if (!thisVentilation.minIndoorTempSched->checkMinMaxVals(state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
2066 0 : Sched::ShowSevereBadMinMax(
2067 0 : state, eoh, cAlphaFieldNames(4), cAlphaArgs(4), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
2068 0 : ErrorsFound = true;
2069 0 : } else if (!lNumericFieldBlanks(6)) {
2070 0 : ShowWarningCustom(
2071 : state,
2072 : eoh,
2073 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(4), cNumericFieldNames(6), cAlphaFieldNames(4)));
2074 : }
2075 :
2076 : // Max indoor temperature
2077 0 : if (!lNumericFieldBlanks(7)) {
2078 0 : thisVentilation.MaxIndoorTemperature = rNumericArgs(7);
2079 : } else {
2080 0 : thisVentilation.MaxIndoorTemperature = VentilTempLimit;
2081 : }
2082 0 : if ((thisVentilation.MaxIndoorTemperature < -VentilTempLimit) || (thisVentilation.MaxIndoorTemperature > VentilTempLimit)) {
2083 0 : ShowSevereCustom(state, eoh, format("{} must be between {}C and {}C", cNumericFieldNames(7), -VentilTempLimit, VentilTempLimit));
2084 0 : ErrorsFound = true;
2085 : }
2086 :
2087 0 : if (!lAlphaFieldBlanks(5)) {
2088 0 : thisVentilation.maxIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(5));
2089 : }
2090 :
2091 0 : if (lAlphaFieldBlanks(5)) {
2092 0 : if (lNumericFieldBlanks(7)) {
2093 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(7), format("The default value will be used ({:.1R})",
2094 : // VentilTempLimit));
2095 : }
2096 0 : } else if (thisVentilation.maxIndoorTempSched == nullptr) {
2097 0 : ShowWarningItemNotFound(state,
2098 : eoh,
2099 0 : cAlphaFieldNames(5),
2100 0 : cAlphaArgs(5),
2101 0 : format("The default value will be used ({:.1R})", thisVentilation.MaxIndoorTemperature));
2102 0 : } else if (!thisVentilation.maxIndoorTempSched->checkMinMaxVals(state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
2103 0 : Sched::ShowSevereBadMinMax(
2104 0 : state, eoh, cAlphaFieldNames(5), cAlphaArgs(5), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
2105 0 : ErrorsFound = true;
2106 0 : } else if (!lNumericFieldBlanks(7)) {
2107 0 : ShowWarningCustom(
2108 : state,
2109 : eoh,
2110 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(5), cNumericFieldNames(7), cAlphaFieldNames(5)));
2111 : }
2112 :
2113 0 : if (!lNumericFieldBlanks(8)) {
2114 0 : thisVentilation.DelTemperature = rNumericArgs(8);
2115 : } else {
2116 0 : thisVentilation.DelTemperature = -VentilTempLimit;
2117 : }
2118 :
2119 0 : if (!lAlphaFieldBlanks(6)) {
2120 0 : thisVentilation.deltaTempSched = Sched::GetSchedule(state, cAlphaArgs(6));
2121 : }
2122 :
2123 0 : if (lAlphaFieldBlanks(6)) {
2124 0 : if (lNumericFieldBlanks(8)) {
2125 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(8), format("The default value will be used ({:.1R})",
2126 : // VentilTempLimit));
2127 : }
2128 0 : } else if (thisVentilation.deltaTempSched == nullptr) {
2129 0 : ShowWarningItemNotFound(state,
2130 : eoh,
2131 0 : cAlphaFieldNames(6),
2132 0 : cAlphaArgs(6),
2133 0 : format("The default value will be used ({:.1R})", thisVentilation.DelTemperature));
2134 0 : } else if (!thisVentilation.deltaTempSched->checkMinVal(state, Clusive::In, -VentilTempLimit)) {
2135 0 : Sched::ShowSevereBadMin(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6), Clusive::In, -VentilTempLimit);
2136 0 : ErrorsFound = true;
2137 0 : } else if (!lNumericFieldBlanks(8)) {
2138 0 : ShowWarningCustom(
2139 : state,
2140 : eoh,
2141 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(6), cNumericFieldNames(8), cAlphaFieldNames(6)));
2142 : }
2143 :
2144 : // Min outdoor temp
2145 0 : thisVentilation.MinOutdoorTemperature = !lNumericFieldBlanks(9) ? rNumericArgs(9) : -VentilTempLimit;
2146 0 : if ((thisVentilation.MinOutdoorTemperature < -VentilTempLimit) || (thisVentilation.MinOutdoorTemperature > VentilTempLimit)) {
2147 0 : ShowSevereError(state,
2148 0 : format("{}{} statement = {} must have {} between -100C and 100C",
2149 : RoutineName,
2150 : cCurrentModuleObject,
2151 : cAlphaArgs(1),
2152 : cNumericFieldNames(9)));
2153 0 : ErrorsFound = true;
2154 : }
2155 :
2156 0 : if (!lAlphaFieldBlanks(7)) {
2157 0 : thisVentilation.minOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(7));
2158 : }
2159 :
2160 0 : if (lAlphaFieldBlanks(7)) {
2161 0 : if (lNumericFieldBlanks(9)) {
2162 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(9), format("The default value will be used ({:.1R})",
2163 : // VentilTempLimit));
2164 : }
2165 0 : } else if (thisVentilation.minOutdoorTempSched == nullptr) {
2166 0 : ShowWarningItemNotFound(state,
2167 : eoh,
2168 0 : cAlphaFieldNames(7),
2169 0 : cAlphaArgs(7),
2170 0 : format("The default value will be used ({:.1R})", thisVentilation.MinOutdoorTemperature));
2171 0 : } else if (!thisVentilation.minOutdoorTempSched->checkMinMaxVals(
2172 : state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
2173 0 : Sched::ShowSevereBadMinMax(
2174 0 : state, eoh, cAlphaFieldNames(7), cAlphaArgs(7), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
2175 0 : ErrorsFound = true;
2176 0 : } else if (!lNumericFieldBlanks(9)) {
2177 0 : ShowWarningCustom(
2178 : state,
2179 : eoh,
2180 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(7), cNumericFieldNames(9), cAlphaFieldNames(7)));
2181 : }
2182 :
2183 : // Max outdoor temp
2184 0 : thisVentilation.MaxOutdoorTemperature = !lNumericFieldBlanks(10) ? rNumericArgs(10) : VentilTempLimit;
2185 0 : if ((thisVentilation.MaxOutdoorTemperature < -VentilTempLimit) || (thisVentilation.MaxOutdoorTemperature > VentilTempLimit)) {
2186 0 : ShowSevereError(state,
2187 0 : format("{}{} statement = {} must have a {} between -100C and 100C",
2188 : RoutineName,
2189 : cCurrentModuleObject,
2190 : cAlphaArgs(1),
2191 : cNumericFieldNames(10)));
2192 0 : ErrorsFound = true;
2193 : }
2194 :
2195 0 : if (!lAlphaFieldBlanks(8)) {
2196 0 : thisVentilation.maxOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(8));
2197 : }
2198 :
2199 0 : if (lAlphaFieldBlanks(8)) {
2200 0 : if (lNumericFieldBlanks(10)) {
2201 : // ShowWarningEmptyField(state, eoh, cNumericFieldNames(10), format("The default value will be used ({:.1R})",
2202 : // VentilTempLimit));
2203 : }
2204 0 : } else if (thisVentilation.maxOutdoorTempSched == nullptr) {
2205 0 : ShowWarningItemNotFound(state,
2206 : eoh,
2207 0 : cAlphaFieldNames(8),
2208 0 : cAlphaArgs(8),
2209 0 : format("The default value will be used ({:.1R})", thisVentilation.MaxOutdoorTemperature));
2210 0 : } else if (!thisVentilation.maxOutdoorTempSched->checkMinMaxVals(
2211 : state, Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit)) {
2212 0 : Sched::ShowSevereBadMinMax(
2213 0 : state, eoh, cAlphaFieldNames(8), cAlphaArgs(8), Clusive::In, -VentilTempLimit, Clusive::In, VentilTempLimit);
2214 0 : ErrorsFound = true;
2215 0 : } else if (!lNumericFieldBlanks(10)) {
2216 0 : ShowWarningCustom(
2217 : state,
2218 : eoh,
2219 0 : format("Both {} and {} provided, {} will be used.", cAlphaFieldNames(8), cNumericFieldNames(10), cAlphaFieldNames(8)));
2220 : }
2221 :
2222 : // Max wind speed
2223 0 : thisVentilation.MaxWindSpeed = !lNumericFieldBlanks(11) ? rNumericArgs(11) : VentilWSLimit;
2224 0 : if ((thisVentilation.MaxWindSpeed < -VentilWSLimit) || (thisVentilation.MaxWindSpeed > VentilWSLimit)) {
2225 0 : ShowSevereError(state,
2226 0 : format("{}{} statement = {} must have a maximum wind speed between 0 m/s and 40 m/s",
2227 : RoutineName,
2228 : cCurrentModuleObject,
2229 : cAlphaArgs(1)));
2230 0 : ErrorsFound = true;
2231 : }
2232 :
2233 : // Report variables should be added for individual VENTILATION objects, in addition to zone totals below
2234 :
2235 0 : if (thisVentilation.ZonePtr > 0) {
2236 0 : if (RepVarSet(thisVentilation.ZonePtr) && !thisZone.zoneOAQuadratureSum) {
2237 0 : RepVarSet(thisVentilation.ZonePtr) = false;
2238 0 : SetupOutputVariable(state,
2239 : "Zone Ventilation Sensible Heat Loss Energy",
2240 : Constant::Units::J,
2241 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilHeatLoss,
2242 : OutputProcessor::TimeStepType::System,
2243 : OutputProcessor::StoreType::Sum,
2244 0 : thisZone.Name);
2245 0 : SetupOutputVariable(state,
2246 : "Zone Ventilation Sensible Heat Gain Energy",
2247 : Constant::Units::J,
2248 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilHeatGain,
2249 : OutputProcessor::TimeStepType::System,
2250 : OutputProcessor::StoreType::Sum,
2251 0 : thisZone.Name);
2252 0 : SetupOutputVariable(state,
2253 : "Zone Ventilation Latent Heat Loss Energy",
2254 : Constant::Units::J,
2255 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilLatentLoss,
2256 : OutputProcessor::TimeStepType::System,
2257 : OutputProcessor::StoreType::Sum,
2258 0 : thisZone.Name);
2259 0 : SetupOutputVariable(state,
2260 : "Zone Ventilation Latent Heat Gain Energy",
2261 : Constant::Units::J,
2262 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilLatentGain,
2263 : OutputProcessor::TimeStepType::System,
2264 : OutputProcessor::StoreType::Sum,
2265 0 : thisZone.Name);
2266 0 : SetupOutputVariable(state,
2267 : "Zone Ventilation Total Heat Loss Energy",
2268 : Constant::Units::J,
2269 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilTotalLoss,
2270 : OutputProcessor::TimeStepType::System,
2271 : OutputProcessor::StoreType::Sum,
2272 0 : thisZone.Name);
2273 0 : SetupOutputVariable(state,
2274 : "Zone Ventilation Total Heat Gain Energy",
2275 : Constant::Units::J,
2276 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilTotalGain,
2277 : OutputProcessor::TimeStepType::System,
2278 : OutputProcessor::StoreType::Sum,
2279 0 : thisZone.Name);
2280 0 : SetupOutputVariable(state,
2281 : "Zone Ventilation Current Density Volume Flow Rate",
2282 : Constant::Units::m3_s,
2283 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVdotCurDensity,
2284 : OutputProcessor::TimeStepType::System,
2285 : OutputProcessor::StoreType::Average,
2286 0 : thisZone.Name);
2287 0 : SetupOutputVariable(state,
2288 : "Zone Ventilation Standard Density Volume Flow Rate",
2289 : Constant::Units::m3_s,
2290 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVdotStdDensity,
2291 : OutputProcessor::TimeStepType::System,
2292 : OutputProcessor::StoreType::Average,
2293 0 : thisZone.Name);
2294 0 : SetupOutputVariable(state,
2295 : "Zone Ventilation Outdoor Density Volume Flow Rate",
2296 : Constant::Units::m3_s,
2297 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVdotOutDensity,
2298 : OutputProcessor::TimeStepType::System,
2299 : OutputProcessor::StoreType::Average,
2300 0 : thisZone.Name);
2301 0 : SetupOutputVariable(state,
2302 : "Zone Ventilation Current Density Volume",
2303 : Constant::Units::m3,
2304 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVolumeCurDensity,
2305 : OutputProcessor::TimeStepType::System,
2306 : OutputProcessor::StoreType::Sum,
2307 0 : thisZone.Name);
2308 0 : SetupOutputVariable(state,
2309 : "Zone Ventilation Standard Density Volume",
2310 : Constant::Units::m3,
2311 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilVolumeStdDensity,
2312 : OutputProcessor::TimeStepType::System,
2313 : OutputProcessor::StoreType::Sum,
2314 0 : thisZone.Name);
2315 0 : SetupOutputVariable(state,
2316 : "Zone Ventilation Mass",
2317 : Constant::Units::kg,
2318 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilMass,
2319 : OutputProcessor::TimeStepType::System,
2320 : OutputProcessor::StoreType::Sum,
2321 0 : thisZone.Name);
2322 0 : SetupOutputVariable(state,
2323 : "Zone Ventilation Mass Flow Rate",
2324 : Constant::Units::kg_s,
2325 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilMdot,
2326 : OutputProcessor::TimeStepType::System,
2327 : OutputProcessor::StoreType::Average,
2328 0 : thisZone.Name);
2329 0 : SetupOutputVariable(state,
2330 : "Zone Ventilation Current Density Air Change Rate",
2331 : Constant::Units::ach,
2332 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirChangeRateCurDensity,
2333 : OutputProcessor::TimeStepType::System,
2334 : OutputProcessor::StoreType::Average,
2335 0 : thisZone.Name);
2336 0 : SetupOutputVariable(state,
2337 : "Zone Ventilation Standard Density Air Change Rate",
2338 : Constant::Units::ach,
2339 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirChangeRateStdDensity,
2340 : OutputProcessor::TimeStepType::System,
2341 : OutputProcessor::StoreType::Average,
2342 0 : thisZone.Name);
2343 0 : SetupOutputVariable(state,
2344 : "Zone Ventilation Outdoor Density Air Change Rate",
2345 : Constant::Units::ach,
2346 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirChangeRateOutDensity,
2347 : OutputProcessor::TimeStepType::System,
2348 : OutputProcessor::StoreType::Average,
2349 0 : thisZone.Name);
2350 0 : SetupOutputVariable(state,
2351 : "Zone Ventilation Fan Electricity Energy",
2352 : Constant::Units::J,
2353 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilFanElec,
2354 : OutputProcessor::TimeStepType::System,
2355 : OutputProcessor::StoreType::Sum,
2356 0 : thisZone.Name,
2357 : Constant::eResource::Electricity,
2358 : OutputProcessor::Group::Building,
2359 : OutputProcessor::EndUseCat::Fans,
2360 : "Ventilation (simple)",
2361 0 : thisZone.Name);
2362 0 : SetupOutputVariable(state,
2363 : "Zone Ventilation Air Inlet Temperature",
2364 : Constant::Units::C,
2365 0 : state.dataHeatBal->ZnAirRpt(thisVentilation.ZonePtr).VentilAirTemp,
2366 : OutputProcessor::TimeStepType::System,
2367 : OutputProcessor::StoreType::Average,
2368 0 : thisZone.Name);
2369 : }
2370 : }
2371 :
2372 0 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
2373 0 : SetupEMSActuator(state,
2374 : "Zone Ventilation",
2375 : thisVentilation.Name,
2376 : "Air Exchange Flow Rate",
2377 : "[m3/s]",
2378 0 : thisVentilation.EMSSimpleVentOn,
2379 0 : thisVentilation.EMSimpleVentFlowRate);
2380 : }
2381 : }
2382 : }
2383 : }
2384 :
2385 : // Set up and process ZoneMixing and ZoneCrossMixing inputs
2386 :
2387 120 : RepVarSet = true;
2388 :
2389 120 : cCurrentModuleObject = "ZoneMixing";
2390 120 : int numZoneMixingInputObjects = 0;
2391 240 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> zoneMixingInputObjects;
2392 120 : InternalHeatGains::setupIHGZonesAndSpaces(state,
2393 : cCurrentModuleObject,
2394 : zoneMixingInputObjects,
2395 : numZoneMixingInputObjects,
2396 120 : state.dataHeatBal->TotMixing,
2397 : ErrorsFound,
2398 : zoneListNotAllowed);
2399 :
2400 120 : if (state.dataHeatBal->TotMixing > 0) {
2401 8 : cCurrentModuleObject = "ZoneMixing";
2402 8 : state.dataHeatBal->Mixing.allocate(state.dataHeatBal->TotMixing);
2403 8 : int mixingNum = 0;
2404 21 : for (int mixingInputNum = 1; mixingInputNum <= numZoneMixingInputObjects; ++mixingInputNum) {
2405 :
2406 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2407 : cCurrentModuleObject,
2408 : mixingInputNum,
2409 : cAlphaArgs,
2410 : NumAlpha,
2411 : rNumericArgs,
2412 : NumNumber,
2413 : IOStat,
2414 : lNumericFieldBlanks,
2415 : lAlphaFieldBlanks,
2416 : cAlphaFieldNames,
2417 : cNumericFieldNames);
2418 :
2419 13 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
2420 : // Create one Mixing instance for every space associated with this input object
2421 13 : auto const &thisMixingInput = zoneMixingInputObjects(mixingInputNum);
2422 27 : for (int Item1 = 1; Item1 <= thisMixingInput.numOfSpaces; ++Item1) {
2423 14 : ++mixingNum;
2424 14 : auto &thisMixing = state.dataHeatBal->Mixing(mixingNum);
2425 14 : thisMixing.Name = thisMixingInput.names(Item1);
2426 14 : thisMixing.spaceIndex = thisMixingInput.spaceNums(Item1);
2427 14 : auto const &thisSpace = state.dataHeatBal->space(thisMixing.spaceIndex);
2428 14 : thisMixing.ZonePtr = thisSpace.zoneNum;
2429 14 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
2430 :
2431 14 : if (lAlphaFieldBlanks(3)) {
2432 5 : thisMixing.sched = Sched::GetScheduleAlwaysOn(state); // Not an availability schedule, but defaults to constant-1.0
2433 9 : } else if ((thisMixing.sched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
2434 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
2435 0 : ErrorsFound = true;
2436 : }
2437 :
2438 : // Mixing equipment design level calculation method
2439 14 : AirflowSpec flow = static_cast<AirflowSpec>(getEnumValue(airflowSpecNamesUC, cAlphaArgs(4)));
2440 14 : switch (flow) {
2441 9 : case AirflowSpec::FlowPerZone:
2442 9 : thisMixing.DesignLevel = rNumericArgs(1);
2443 9 : if (lNumericFieldBlanks(1)) {
2444 0 : ShowWarningError(state,
2445 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Mixing will result.",
2446 : RoutineName,
2447 : cCurrentModuleObject,
2448 0 : thisMixingInput.Name,
2449 : cAlphaFieldNames(4),
2450 : cNumericFieldNames(1)));
2451 : } else {
2452 9 : Real64 spaceFrac = 1.0;
2453 9 : if (!thisMixingInput.spaceListActive && (thisMixingInput.numOfSpaces > 1)) {
2454 0 : Real64 const zoneVolume = thisZone.Volume;
2455 0 : if (zoneVolume > 0.0) {
2456 0 : spaceFrac = thisSpace.Volume / zoneVolume;
2457 : } else {
2458 0 : ShowSevereError(state, format("{}Zone volume is zero when allocating Mixing to Spaces.", RoutineName));
2459 0 : ShowContinueError(
2460 0 : state, format("Occurs for {}=\"{}\" in Zone=\"{}\".", cCurrentModuleObject, thisMixingInput.Name, thisZone.Name));
2461 0 : ErrorsFound = true;
2462 : }
2463 : }
2464 :
2465 9 : thisMixing.DesignLevel = rNumericArgs(1) * spaceFrac;
2466 : }
2467 9 : break;
2468 :
2469 5 : case AirflowSpec::FlowPerArea:
2470 5 : if (thisMixing.spaceIndex != 0) {
2471 5 : if (rNumericArgs(2) >= 0.0) {
2472 5 : thisMixing.DesignLevel = rNumericArgs(2) * thisSpace.FloorArea;
2473 5 : if (thisMixing.spaceIndex > 0) {
2474 5 : if (thisZone.FloorArea <= 0.0) {
2475 0 : ShowWarningError(state,
2476 0 : format("{}{}=\"{}\", {} specifies {}, but Space Floor Area = 0. 0 Mixing will result.",
2477 : RoutineName,
2478 : cCurrentModuleObject,
2479 0 : thisMixingInput.Name,
2480 : cAlphaFieldNames(4),
2481 : cNumericFieldNames(2)));
2482 : }
2483 : }
2484 : } else {
2485 0 : ShowSevereError(state,
2486 0 : format("{}{}=\"{}\", invalid flow/area specification [<0.0]={:.3R}",
2487 : RoutineName,
2488 : cCurrentModuleObject,
2489 0 : thisMixingInput.Name,
2490 : rNumericArgs(2)));
2491 0 : ErrorsFound = true;
2492 : }
2493 : }
2494 5 : if (lNumericFieldBlanks(2)) {
2495 0 : ShowWarningError(state,
2496 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Mixing will result.",
2497 : RoutineName,
2498 : cCurrentModuleObject,
2499 0 : thisMixingInput.Name,
2500 : cAlphaFieldNames(4),
2501 : cNumericFieldNames(2)));
2502 : }
2503 5 : break;
2504 :
2505 0 : case AirflowSpec::FlowPerPerson:
2506 0 : if (thisMixing.spaceIndex != 0) {
2507 0 : if (rNumericArgs(3) >= 0.0) {
2508 0 : thisMixing.DesignLevel = rNumericArgs(3) * thisSpace.TotOccupants;
2509 0 : if (thisSpace.TotOccupants <= 0.0) {
2510 0 : ShowWarningError(state,
2511 0 : format("{}{}=\"{}\", {} specifies {}, but Space Total Occupants = 0. 0 Mixing will result.",
2512 : RoutineName,
2513 : cCurrentModuleObject,
2514 0 : thisMixingInput.Name,
2515 : cAlphaFieldNames(4),
2516 : cNumericFieldNames(3)));
2517 : }
2518 : } else {
2519 0 : ShowSevereError(state,
2520 0 : format("{}{}=\"{}\", invalid flow/person specification [<0.0]={:.3R}",
2521 : RoutineName,
2522 : cCurrentModuleObject,
2523 0 : thisMixingInput.Name,
2524 : rNumericArgs(3)));
2525 0 : ErrorsFound = true;
2526 : }
2527 : }
2528 0 : if (lNumericFieldBlanks(3)) {
2529 0 : ShowWarningError(state,
2530 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Mixing will result.",
2531 : RoutineName,
2532 : cCurrentModuleObject,
2533 0 : thisMixingInput.Name,
2534 : cAlphaFieldNames(4),
2535 : cNumericFieldNames(3)));
2536 : }
2537 0 : break;
2538 :
2539 0 : case AirflowSpec::AirChanges:
2540 0 : if (thisMixing.spaceIndex != 0) {
2541 0 : if (rNumericArgs(4) >= 0.0) {
2542 0 : thisMixing.DesignLevel = rNumericArgs(4) * thisSpace.Volume / Constant::rSecsInHour;
2543 0 : if (thisSpace.Volume <= 0.0) {
2544 0 : ShowWarningError(state,
2545 0 : format("{}{}=\"{}\", {} specifies {}, but Space Volume = 0. 0 Mixing will result.",
2546 : RoutineName,
2547 : cCurrentModuleObject,
2548 0 : thisMixingInput.Name,
2549 : cAlphaFieldNames(4),
2550 : cNumericFieldNames(4)));
2551 : }
2552 : } else {
2553 0 : ShowSevereError(state,
2554 0 : format("{}{}=\"{}\", invalid ACH (air changes per hour) specification [<0.0]={:.3R}",
2555 : RoutineName,
2556 : cCurrentModuleObject,
2557 0 : thisMixingInput.Name,
2558 : rNumericArgs(4)));
2559 0 : ErrorsFound = true;
2560 : }
2561 : }
2562 0 : if (lNumericFieldBlanks(4)) {
2563 0 : ShowWarningError(state,
2564 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Mixing will result.",
2565 : RoutineName,
2566 : cCurrentModuleObject,
2567 0 : thisMixingInput.Name,
2568 : cAlphaFieldNames(4),
2569 : cNumericFieldNames(4)));
2570 : }
2571 0 : break;
2572 :
2573 0 : default:
2574 0 : ShowSevereError(
2575 0 : state, format("{}{}=\"{}\", invalid calculation method={}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(4)));
2576 0 : ErrorsFound = true;
2577 : }
2578 :
2579 14 : thisMixing.fromSpaceIndex = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->space);
2580 14 : if (thisMixing.fromSpaceIndex == 0) {
2581 1 : thisMixing.FromZone = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
2582 : } else {
2583 13 : thisMixing.FromZone = state.dataHeatBal->space(thisMixing.fromSpaceIndex).zoneNum;
2584 : }
2585 14 : if ((thisMixing.FromZone == 0) && (thisMixing.fromSpaceIndex == 0)) {
2586 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
2587 0 : ErrorsFound = true;
2588 : }
2589 14 : thisMixing.DeltaTemperature = rNumericArgs(5);
2590 :
2591 14 : if (NumAlpha > 5) {
2592 0 : if (lAlphaFieldBlanks(6)) {
2593 0 : if (lNumericFieldBlanks(5)) {
2594 0 : ShowWarningCustom(state,
2595 : eoh,
2596 0 : format("{} and {} are empty, a default temperature of {:.1R}C will be used.",
2597 : cAlphaFieldNames(6),
2598 : cNumericFieldNames(5),
2599 0 : -MixingTempLimit));
2600 : }
2601 0 : } else if ((thisMixing.deltaTempSched = Sched::GetSchedule(state, cAlphaArgs(6))) == nullptr) {
2602 0 : ShowWarningItemNotFound(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6), "");
2603 0 : if (lNumericFieldBlanks(5)) {
2604 0 : ShowContinueError(state, format("a default temperature of {:.1R}C will be used.", -MixingTempLimit));
2605 : }
2606 0 : } else if (!thisMixing.deltaTempSched->checkMinVal(state, Clusive::In, -MixingTempLimit)) {
2607 0 : Sched::ShowSevereBadMin(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6), Clusive::In, -MixingTempLimit);
2608 0 : ErrorsFound = true;
2609 0 : } else if (!lNumericFieldBlanks(5))
2610 0 : ShowWarningCustom(
2611 : state,
2612 : eoh,
2613 0 : format("{} and {} are provided, {} will be used.", cAlphaFieldNames(6), cNumericFieldNames(5), cAlphaFieldNames(6)));
2614 : }
2615 :
2616 : // Min indoor temp
2617 14 : if (NumAlpha > 6) {
2618 0 : if (lAlphaFieldBlanks(7)) {
2619 : // Is this an error or is there a default?
2620 0 : } else if ((thisMixing.minIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(7))) == nullptr) {
2621 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(7), cAlphaArgs(7));
2622 0 : ErrorsFound = true;
2623 0 : } else if (!thisMixing.minIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2624 0 : Sched::ShowSevereBadMinMax(
2625 0 : state, eoh, cAlphaFieldNames(7), cAlphaArgs(7), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2626 0 : ErrorsFound = true;
2627 : }
2628 : }
2629 :
2630 : // Max indoor temp
2631 14 : if (NumAlpha > 7) {
2632 0 : if (lAlphaFieldBlanks(8)) {
2633 0 : } else if ((thisMixing.maxIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(8))) == nullptr) {
2634 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8));
2635 0 : ErrorsFound = true;
2636 0 : } else if (!thisMixing.maxIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2637 0 : Sched::ShowSevereBadMinMax(
2638 0 : state, eoh, cAlphaFieldNames(8), cAlphaArgs(8), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2639 0 : ErrorsFound = true;
2640 : }
2641 : }
2642 :
2643 : // Min source temp
2644 14 : if (NumAlpha > 8) {
2645 0 : if (lAlphaFieldBlanks(9)) {
2646 0 : } else if ((thisMixing.minSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(9))) == nullptr) {
2647 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(9), cAlphaArgs(9));
2648 0 : ErrorsFound = true;
2649 0 : } else if (!thisMixing.minSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2650 0 : Sched::ShowSevereBadMinMax(
2651 0 : state, eoh, cAlphaFieldNames(9), cAlphaArgs(9), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2652 0 : ErrorsFound = true;
2653 : }
2654 : }
2655 :
2656 : // Max source temp
2657 14 : if (NumAlpha > 9) {
2658 0 : if (lAlphaFieldBlanks(10)) {
2659 0 : } else if ((thisMixing.maxSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(10))) == nullptr) {
2660 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(10), cAlphaArgs(10));
2661 0 : ErrorsFound = true;
2662 0 : } else if (!thisMixing.maxSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2663 0 : Sched::ShowSevereBadMinMax(
2664 0 : state, eoh, cAlphaFieldNames(10), cAlphaArgs(10), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2665 0 : ErrorsFound = true;
2666 : }
2667 : }
2668 :
2669 14 : if (NumAlpha > 10) {
2670 0 : if (lAlphaFieldBlanks(11)) {
2671 0 : } else if ((thisMixing.minOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(11))) == nullptr) {
2672 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(11), cAlphaArgs(11));
2673 0 : ErrorsFound = true;
2674 0 : } else if (!thisMixing.minOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2675 0 : Sched::ShowSevereBadMinMax(
2676 0 : state, eoh, cAlphaFieldNames(11), cAlphaArgs(11), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2677 0 : ErrorsFound = true;
2678 : }
2679 : }
2680 :
2681 : //
2682 14 : if (NumAlpha > 11) {
2683 0 : if (lAlphaFieldBlanks(12)) {
2684 0 : } else if ((thisMixing.maxOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(12))) == nullptr) {
2685 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(12), cAlphaArgs(12));
2686 0 : ErrorsFound = true;
2687 0 : } else if (!thisMixing.maxOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2688 0 : Sched::ShowSevereBadMinMax(
2689 0 : state, eoh, cAlphaFieldNames(12), cAlphaArgs(12), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2690 0 : ErrorsFound = true;
2691 : }
2692 : }
2693 :
2694 14 : if (thisMixing.ZonePtr > 0) {
2695 14 : if (RepVarSet(thisMixing.ZonePtr)) {
2696 11 : RepVarSet(thisMixing.ZonePtr) = false;
2697 22 : SetupOutputVariable(state,
2698 : "Zone Mixing Volume",
2699 : Constant::Units::m3,
2700 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixVolume,
2701 : OutputProcessor::TimeStepType::System,
2702 : OutputProcessor::StoreType::Sum,
2703 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2704 22 : SetupOutputVariable(state,
2705 : "Zone Mixing Current Density Volume Flow Rate",
2706 : Constant::Units::m3_s,
2707 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixVdotCurDensity,
2708 : OutputProcessor::TimeStepType::System,
2709 : OutputProcessor::StoreType::Average,
2710 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2711 22 : SetupOutputVariable(state,
2712 : "Zone Mixing Standard Density Volume Flow Rate",
2713 : Constant::Units::m3_s,
2714 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixVdotStdDensity,
2715 : OutputProcessor::TimeStepType::System,
2716 : OutputProcessor::StoreType::Average,
2717 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2718 22 : SetupOutputVariable(state,
2719 : "Zone Mixing Mass",
2720 : Constant::Units::kg,
2721 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixMass,
2722 : OutputProcessor::TimeStepType::System,
2723 : OutputProcessor::StoreType::Sum,
2724 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2725 22 : SetupOutputVariable(state,
2726 : "Zone Mixing Mass Flow Rate",
2727 : Constant::Units::kg_s,
2728 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixMdot,
2729 : OutputProcessor::TimeStepType::System,
2730 : OutputProcessor::StoreType::Average,
2731 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2732 22 : SetupOutputVariable(state,
2733 : "Zone Mixing Sensible Heat Loss Energy",
2734 : Constant::Units::J,
2735 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixHeatLoss,
2736 : OutputProcessor::TimeStepType::System,
2737 : OutputProcessor::StoreType::Sum,
2738 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2739 22 : SetupOutputVariable(state,
2740 : "Zone Mixing Sensible Heat Gain Energy",
2741 : Constant::Units::J,
2742 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixHeatGain,
2743 : OutputProcessor::TimeStepType::System,
2744 : OutputProcessor::StoreType::Sum,
2745 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2746 22 : SetupOutputVariable(state,
2747 : "Zone Mixing Latent Heat Loss Energy",
2748 : Constant::Units::J,
2749 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixLatentLoss,
2750 : OutputProcessor::TimeStepType::System,
2751 : OutputProcessor::StoreType::Sum,
2752 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2753 22 : SetupOutputVariable(state,
2754 : "Zone Mixing Latent Heat Gain Energy",
2755 : Constant::Units::J,
2756 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixLatentGain,
2757 : OutputProcessor::TimeStepType::System,
2758 : OutputProcessor::StoreType::Sum,
2759 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2760 22 : SetupOutputVariable(state,
2761 : "Zone Mixing Total Heat Loss Energy",
2762 : Constant::Units::J,
2763 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixTotalLoss,
2764 : OutputProcessor::TimeStepType::System,
2765 : OutputProcessor::StoreType::Sum,
2766 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2767 22 : SetupOutputVariable(state,
2768 : "Zone Mixing Total Heat Gain Energy",
2769 : Constant::Units::J,
2770 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixTotalGain,
2771 : OutputProcessor::TimeStepType::System,
2772 : OutputProcessor::StoreType::Sum,
2773 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2774 : }
2775 : }
2776 14 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
2777 0 : SetupEMSActuator(state,
2778 : "ZoneMixing",
2779 : thisMixing.Name,
2780 : "Air Exchange Flow Rate",
2781 : "[m3/s]",
2782 0 : thisMixing.EMSSimpleMixingOn,
2783 0 : thisMixing.EMSimpleMixingFlowRate);
2784 : }
2785 : }
2786 : }
2787 : }
2788 :
2789 : // allocate MassConservation
2790 120 : state.dataHeatBal->MassConservation.allocate(state.dataGlobal->NumOfZones);
2791 :
2792 : // added by BAN, 02/14
2793 120 : if (state.dataHeatBal->TotMixing > 0) {
2794 8 : ZoneMixingNum.allocate(state.dataHeatBal->TotMixing);
2795 : // get source zones mixing objects index
2796 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2797 18 : int SourceCount = 0;
2798 50 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
2799 32 : if (ZoneNum == state.dataHeatBal->Mixing(Loop).FromZone) {
2800 14 : SourceCount += 1;
2801 14 : ZoneMixingNum(SourceCount) = Loop;
2802 : }
2803 : }
2804 : // save mixing objects index for zones which serve as a source zone
2805 18 : state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject = SourceCount;
2806 18 : if (SourceCount > 0) {
2807 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingSourcesPtr.allocate(SourceCount);
2808 25 : for (int Loop = 1; Loop <= SourceCount; ++Loop) {
2809 14 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingSourcesPtr(Loop) = ZoneMixingNum(Loop);
2810 : }
2811 : }
2812 : }
2813 :
2814 : // check zones which are used only as a source zones
2815 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2816 50 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
2817 32 : if (ZoneNum != state.dataHeatBal->Mixing(Loop).FromZone) continue;
2818 14 : state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone = true;
2819 35 : for (int Loop1 = 1; Loop1 <= state.dataHeatBal->TotMixing; ++Loop1) {
2820 28 : if (ZoneNum == state.dataHeatBal->Mixing(Loop1).ZonePtr) {
2821 7 : state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone = false;
2822 7 : break;
2823 : }
2824 : }
2825 : }
2826 : }
2827 : // get receiving zones mixing objects index
2828 8 : ZoneMixingNum = 0;
2829 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2830 18 : int ReceivingCount = 0;
2831 50 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
2832 32 : if (ZoneNum == state.dataHeatBal->Mixing(Loop).ZonePtr) {
2833 14 : ReceivingCount += 1;
2834 14 : ZoneMixingNum(ReceivingCount) = Loop;
2835 : }
2836 : }
2837 : // save mixing objects index for zones which serve as a receiving zone
2838 18 : state.dataHeatBal->MassConservation(ZoneNum).NumReceivingZonesMixingObject = ReceivingCount;
2839 18 : if (ReceivingCount > 0) {
2840 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingPtr.allocate(ReceivingCount);
2841 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingFr.allocate(ReceivingCount);
2842 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingFr = 0.0;
2843 25 : for (int Loop = 1; Loop <= ReceivingCount; ++Loop) {
2844 14 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingPtr(Loop) = ZoneMixingNum(Loop);
2845 : }
2846 : }
2847 : // flag zones used as both source and receiving zone
2848 29 : if (state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject > 0 &&
2849 11 : state.dataHeatBal->MassConservation(ZoneNum).NumReceivingZonesMixingObject > 0) {
2850 4 : state.dataHeatBal->MassConservation(ZoneNum).IsSourceAndReceivingZone = true;
2851 : }
2852 : }
2853 8 : if (allocated(ZoneMixingNum)) ZoneMixingNum.deallocate();
2854 : }
2855 :
2856 : // zone mass conservation calculation order starts with receiving zones
2857 : // and then proceeds to source zones
2858 120 : int Loop2 = 0;
2859 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2860 319 : if (!state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone &&
2861 156 : !state.dataHeatBal->MassConservation(ZoneNum).IsSourceAndReceivingZone) {
2862 152 : Loop2 += 1;
2863 152 : state.dataHeatBalFanSys->ZoneReOrder(Loop2) = ZoneNum;
2864 : }
2865 : }
2866 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2867 163 : if (state.dataHeatBal->MassConservation(ZoneNum).IsSourceAndReceivingZone) {
2868 4 : Loop2 += 1;
2869 4 : state.dataHeatBalFanSys->ZoneReOrder(Loop2) = ZoneNum;
2870 : }
2871 : }
2872 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2873 163 : if (state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone) {
2874 7 : Loop2 += 1;
2875 7 : state.dataHeatBalFanSys->ZoneReOrder(Loop2) = ZoneNum;
2876 : }
2877 : }
2878 :
2879 120 : cCurrentModuleObject = "ZoneCrossMixing";
2880 120 : int numZoneCrossMixingInputObjects = 0;
2881 120 : int totZoneCrossMixing = 0; // Total ZoneCrossMixing instances after expansion to spaces
2882 240 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> zoneCrossMixingInputObjects;
2883 120 : InternalHeatGains::setupIHGZonesAndSpaces(state,
2884 : cCurrentModuleObject,
2885 : zoneCrossMixingInputObjects,
2886 : numZoneCrossMixingInputObjects,
2887 : totZoneCrossMixing,
2888 : ErrorsFound,
2889 : zoneListNotAllowed);
2890 120 : state.dataHeatBal->TotCrossMixing = totZoneCrossMixing + state.dataHeatBal->airBoundaryMixing.size();
2891 :
2892 120 : if (state.dataHeatBal->TotCrossMixing > 0) {
2893 2 : cCurrentModuleObject = "ZoneCrossMixing";
2894 2 : state.dataHeatBal->CrossMixing.allocate(state.dataHeatBal->TotCrossMixing);
2895 :
2896 2 : int mixingNum = 0;
2897 11 : for (int mixingInputNum = 1; mixingInputNum <= numZoneCrossMixingInputObjects; ++mixingInputNum) {
2898 :
2899 9 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2900 : cCurrentModuleObject,
2901 : mixingInputNum,
2902 : cAlphaArgs,
2903 : NumAlpha,
2904 : rNumericArgs,
2905 : NumNumber,
2906 : IOStat,
2907 : lNumericFieldBlanks,
2908 : lAlphaFieldBlanks,
2909 : cAlphaFieldNames,
2910 : cNumericFieldNames);
2911 :
2912 9 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
2913 :
2914 : // Create one Mixing instance for every space associated with this input object
2915 9 : auto const &thisMixingInput = zoneCrossMixingInputObjects(mixingInputNum);
2916 19 : for (int Item1 = 1; Item1 <= thisMixingInput.numOfSpaces; ++Item1) {
2917 10 : ++mixingNum;
2918 10 : auto &thisMixing = state.dataHeatBal->CrossMixing(mixingNum);
2919 10 : thisMixing.Name = thisMixingInput.names(Item1);
2920 10 : thisMixing.spaceIndex = thisMixingInput.spaceNums(Item1);
2921 10 : auto const &thisSpace = state.dataHeatBal->space(thisMixing.spaceIndex);
2922 10 : thisMixing.ZonePtr = thisSpace.zoneNum;
2923 10 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
2924 :
2925 10 : if (lAlphaFieldBlanks(3)) {
2926 5 : thisMixing.sched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
2927 5 : } else if ((thisMixing.sched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
2928 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
2929 0 : ErrorsFound = true;
2930 : }
2931 :
2932 : // Mixing equipment design level calculation method.
2933 10 : AirflowSpec flow = static_cast<AirflowSpec>(getEnumValue(airflowSpecNamesUC, cAlphaArgs(4))); // NOLINT(modernize-use-auto)
2934 10 : switch (flow) {
2935 5 : case AirflowSpec::FlowPerZone:
2936 5 : thisMixing.DesignLevel = rNumericArgs(1);
2937 5 : if (lNumericFieldBlanks(1)) {
2938 0 : ShowWarningError(state,
2939 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
2940 : RoutineName,
2941 : cCurrentModuleObject,
2942 0 : thisMixingInput.Name,
2943 : cAlphaFieldNames(4),
2944 : cNumericFieldNames(1)));
2945 : } else {
2946 5 : Real64 spaceFrac = 1.0;
2947 5 : if (!thisMixingInput.spaceListActive && (thisMixingInput.numOfSpaces > 1)) {
2948 0 : Real64 const zoneVolume = thisZone.Volume;
2949 0 : if (zoneVolume > 0.0) {
2950 0 : spaceFrac = thisSpace.Volume / zoneVolume;
2951 : } else {
2952 0 : ShowSevereError(state, format("{}Zone volume is zero when allocating Cross Mixing to Spaces.", RoutineName));
2953 0 : ShowContinueError(
2954 0 : state, format("Occurs for {}=\"{}\" in Zone=\"{}\".", cCurrentModuleObject, thisMixingInput.Name, thisZone.Name));
2955 0 : ErrorsFound = true;
2956 : }
2957 : }
2958 :
2959 5 : thisMixing.DesignLevel = rNumericArgs(1) * spaceFrac;
2960 : }
2961 5 : break;
2962 :
2963 5 : case AirflowSpec::FlowPerArea:
2964 5 : if (thisMixing.spaceIndex != 0) {
2965 5 : if (rNumericArgs(2) >= 0.0) {
2966 5 : thisMixing.DesignLevel = rNumericArgs(2) * thisSpace.FloorArea;
2967 5 : if (thisMixing.spaceIndex > 0) {
2968 5 : if (thisZone.FloorArea <= 0.0) {
2969 0 : ShowWarningError(state,
2970 0 : format("{}{}=\"{}\", {} specifies {}, but Space Floor Area = 0. 0 Cross Mixing will result.",
2971 : RoutineName,
2972 : cCurrentModuleObject,
2973 0 : thisMixingInput.Name,
2974 : cAlphaFieldNames(4),
2975 : cNumericFieldNames(2)));
2976 : }
2977 : }
2978 : } else {
2979 0 : ShowSevereError(state,
2980 0 : format("{}{}=\"{}\", invalid flow/area specification [<0.0]={:.3R}",
2981 : RoutineName,
2982 : cCurrentModuleObject,
2983 0 : thisMixingInput.Name,
2984 : rNumericArgs(2)));
2985 0 : ErrorsFound = true;
2986 : }
2987 : }
2988 5 : if (lNumericFieldBlanks(2)) {
2989 0 : ShowWarningError(state,
2990 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
2991 : RoutineName,
2992 : cCurrentModuleObject,
2993 0 : thisMixingInput.Name,
2994 : cAlphaFieldNames(4),
2995 : cNumericFieldNames(2)));
2996 : }
2997 5 : break;
2998 :
2999 0 : case AirflowSpec::FlowPerPerson:
3000 0 : if (thisMixing.spaceIndex != 0) {
3001 0 : if (rNumericArgs(3) >= 0.0) {
3002 0 : thisMixing.DesignLevel = rNumericArgs(3) * thisSpace.TotOccupants;
3003 0 : if (thisSpace.TotOccupants <= 0.0) {
3004 0 : ShowWarningError(state,
3005 0 : format("{}{}=\"{}\", {} specifies {}, but Space Total Occupants = 0. 0 Cross Mixing will result.",
3006 : RoutineName,
3007 : cCurrentModuleObject,
3008 0 : thisMixingInput.Name,
3009 : cAlphaFieldNames(4),
3010 : cNumericFieldNames(3)));
3011 : }
3012 : } else {
3013 0 : ShowSevereError(state,
3014 0 : format("{}{}=\"{}\", invalid flow/person specification [<0.0]={:.3R}",
3015 : RoutineName,
3016 : cCurrentModuleObject,
3017 0 : thisMixingInput.Name,
3018 : rNumericArgs(3)));
3019 0 : ErrorsFound = true;
3020 : }
3021 : }
3022 0 : if (lNumericFieldBlanks(3)) {
3023 0 : ShowWarningError(state,
3024 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
3025 : RoutineName,
3026 : cCurrentModuleObject,
3027 0 : thisMixingInput.Name,
3028 : cAlphaFieldNames(4),
3029 : cNumericFieldNames(3)));
3030 : }
3031 0 : break;
3032 :
3033 0 : case AirflowSpec::AirChanges:
3034 0 : if (thisMixing.spaceIndex != 0) {
3035 0 : if (rNumericArgs(4) >= 0.0) {
3036 0 : thisMixing.DesignLevel = rNumericArgs(4) * thisSpace.Volume / Constant::rSecsInHour;
3037 0 : if (thisSpace.Volume <= 0.0) {
3038 0 : ShowWarningError(state,
3039 0 : format("{}{}=\"{}\", {} specifies {}, but Space Volume = 0. 0 Cross Mixing will result.",
3040 : RoutineName,
3041 : cCurrentModuleObject,
3042 0 : thisMixingInput.Name,
3043 : cAlphaFieldNames(4),
3044 : cNumericFieldNames(4)));
3045 : }
3046 : } else {
3047 0 : ShowSevereError(state,
3048 0 : format("{}{}=\"{}\", invalid ACH (air changes per hour) specification [<0.0]={:.3R}",
3049 : RoutineName,
3050 : cCurrentModuleObject,
3051 0 : thisMixingInput.Name,
3052 : rNumericArgs(4)));
3053 0 : ErrorsFound = true;
3054 : }
3055 : }
3056 0 : if (lNumericFieldBlanks(4)) {
3057 0 : ShowWarningError(state,
3058 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
3059 : RoutineName,
3060 : cCurrentModuleObject,
3061 0 : thisMixingInput.Name,
3062 : cAlphaFieldNames(4),
3063 : cNumericFieldNames(4)));
3064 : }
3065 0 : break;
3066 :
3067 0 : default:
3068 0 : ShowSevereError(
3069 0 : state, format("{}{}=\"{}\", invalid calculation method={}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(4)));
3070 0 : ErrorsFound = true;
3071 : }
3072 :
3073 10 : thisMixing.fromSpaceIndex = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->space);
3074 10 : if (thisMixing.fromSpaceIndex == 0) {
3075 1 : thisMixing.FromZone = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
3076 : } else {
3077 9 : thisMixing.FromZone = state.dataHeatBal->space(thisMixing.fromSpaceIndex).zoneNum;
3078 : }
3079 10 : if ((thisMixing.FromZone == 0) && (thisMixing.fromSpaceIndex == 0)) {
3080 0 : ShowSevereError(state,
3081 0 : format("{}{}=\"{}\", invalid (not found) {}=\"{}\".",
3082 : RoutineName,
3083 : cCurrentModuleObject,
3084 : cAlphaArgs(1),
3085 : cAlphaFieldNames(5),
3086 : cAlphaArgs(5)));
3087 0 : ErrorsFound = true;
3088 : }
3089 10 : thisMixing.DeltaTemperature = rNumericArgs(5);
3090 :
3091 10 : if (NumAlpha > 5) {
3092 5 : if (lAlphaFieldBlanks(6)) {
3093 5 : if (lNumericFieldBlanks(5)) {
3094 0 : ShowWarningCustom(state,
3095 : eoh,
3096 0 : format("{} and {} are empty, a default temperature of {:.1R}C will be used.",
3097 : cAlphaFieldNames(6),
3098 : cNumericFieldNames(5),
3099 0 : thisMixing.DeltaTemperature));
3100 : }
3101 0 : } else if ((thisMixing.deltaTempSched = Sched::GetSchedule(state, cAlphaArgs(6))) == nullptr) {
3102 0 : ShowWarningItemNotFound(state,
3103 : eoh,
3104 0 : cAlphaFieldNames(6),
3105 0 : cAlphaArgs(6),
3106 0 : format("Fixed delta temperature {:.1R}C will be used", thisMixing.DeltaTemperature));
3107 0 : } else if (!thisMixing.deltaTempSched->checkMinVal(state, Clusive::In, 0.0)) {
3108 0 : Sched::ShowSevereBadMin(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6), Clusive::In, 0.0);
3109 0 : ErrorsFound = true;
3110 0 : } else if (!lNumericFieldBlanks(5)) {
3111 0 : ShowWarningCustom(
3112 : state,
3113 : eoh,
3114 0 : format("{} and {} provided. {} will be used.", cAlphaFieldNames(6), cNumericFieldNames(5), cAlphaFieldNames(6)));
3115 : }
3116 : }
3117 :
3118 : // Min indoor temp
3119 10 : if (NumAlpha > 6) {
3120 5 : if (lAlphaFieldBlanks(7)) {
3121 5 : } else if ((thisMixing.minIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(7))) == nullptr) {
3122 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(7), cAlphaArgs(7));
3123 0 : ErrorsFound = true;
3124 5 : } else if (!thisMixing.minIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3125 0 : Sched::ShowSevereBadMinMax(
3126 0 : state, eoh, cAlphaFieldNames(7), cAlphaArgs(7), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3127 0 : ErrorsFound = true;
3128 : }
3129 : }
3130 :
3131 : // Max indoor temp
3132 10 : if (NumAlpha > 7) {
3133 5 : if (lAlphaFieldBlanks(8)) {
3134 5 : } else if ((thisMixing.maxIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(8))) == nullptr) {
3135 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8));
3136 0 : ErrorsFound = true;
3137 5 : } else if (!thisMixing.maxIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3138 0 : Sched::ShowSevereBadMinMax(
3139 0 : state, eoh, cAlphaFieldNames(8), cAlphaArgs(8), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3140 0 : ErrorsFound = true;
3141 : }
3142 : }
3143 :
3144 : // Min source temp
3145 10 : if (NumAlpha > 8) {
3146 5 : if (lAlphaFieldBlanks(9)) {
3147 5 : } else if ((thisMixing.minSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(9))) == nullptr) {
3148 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(9), cAlphaArgs(9));
3149 0 : ErrorsFound = true;
3150 5 : } else if (!thisMixing.minSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3151 0 : Sched::ShowSevereBadMinMax(
3152 0 : state, eoh, cAlphaFieldNames(9), cAlphaArgs(9), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3153 0 : ErrorsFound = true;
3154 : }
3155 : }
3156 :
3157 : // Max source temp
3158 10 : if (NumAlpha > 9) {
3159 5 : if (lAlphaFieldBlanks(10)) {
3160 5 : } else if ((thisMixing.maxSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(10))) == nullptr) {
3161 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(10), cAlphaArgs(10));
3162 0 : ErrorsFound = true;
3163 5 : } else if (!thisMixing.maxSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3164 0 : Sched::ShowSevereBadMinMax(
3165 0 : state, eoh, cAlphaFieldNames(10), cAlphaArgs(10), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3166 0 : ErrorsFound = true;
3167 : }
3168 : }
3169 :
3170 : // Min outdoor temp
3171 10 : if (NumAlpha > 10) {
3172 5 : if (lAlphaFieldBlanks(11)) {
3173 5 : } else if ((thisMixing.minOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(11))) == nullptr) {
3174 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(11), cAlphaArgs(11));
3175 0 : ErrorsFound = true;
3176 5 : } else if (!thisMixing.minOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3177 0 : Sched::ShowSevereBadMinMax(
3178 0 : state, eoh, cAlphaFieldNames(11), cAlphaArgs(11), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3179 0 : ErrorsFound = true;
3180 : }
3181 : }
3182 :
3183 10 : if (NumAlpha > 11) {
3184 5 : if (lAlphaFieldBlanks(12)) {
3185 5 : } else if ((thisMixing.maxOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(12))) == nullptr) {
3186 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(12), cAlphaArgs(12));
3187 0 : ErrorsFound = true;
3188 5 : } else if (!thisMixing.maxOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3189 0 : Sched::ShowSevereBadMinMax(
3190 0 : state, eoh, cAlphaFieldNames(12), cAlphaArgs(12), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3191 0 : ErrorsFound = true;
3192 : }
3193 : }
3194 : }
3195 : } // for (mixingInputNum)
3196 :
3197 : // Create CrossMixing objects from air boundary info
3198 2 : for (auto const &thisAirBoundaryMixing : state.dataHeatBal->airBoundaryMixing) {
3199 0 : ++mixingNum;
3200 : // Create CrossMixing object from air boundary info
3201 0 : int space1 = thisAirBoundaryMixing.space1;
3202 0 : int space2 = thisAirBoundaryMixing.space2;
3203 0 : int zone1 = state.dataHeatBal->space(space1).zoneNum;
3204 0 : int zone2 = state.dataHeatBal->space(space2).zoneNum;
3205 0 : auto &thisCrossMizing = state.dataHeatBal->CrossMixing(mixingNum);
3206 0 : thisCrossMizing.Name = fmt::format("Air Boundary Mixing Zones {} and {}", zone1, zone2);
3207 0 : thisCrossMizing.spaceIndex = space1;
3208 0 : thisCrossMizing.ZonePtr = zone1;
3209 0 : thisCrossMizing.sched = thisAirBoundaryMixing.sched;
3210 0 : thisCrossMizing.DesignLevel = thisAirBoundaryMixing.mixingVolumeFlowRate;
3211 0 : thisCrossMizing.FromZone = zone2;
3212 0 : thisCrossMizing.fromSpaceIndex = space2;
3213 : }
3214 2 : assert(mixingNum == state.dataHeatBal->TotCrossMixing);
3215 12 : for (int mixingRepNum = 1; mixingRepNum <= state.dataHeatBal->TotCrossMixing; ++mixingRepNum) {
3216 10 : int zoneNum = state.dataHeatBal->CrossMixing(mixingRepNum).ZonePtr;
3217 10 : if (zoneNum > 0) {
3218 10 : std::string const &zoneName = state.dataHeatBal->Zone(zoneNum).Name;
3219 10 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(zoneNum);
3220 10 : if (RepVarSet(zoneNum)) {
3221 3 : RepVarSet(zoneNum) = false;
3222 6 : SetupOutputVariable(state,
3223 : "Zone Mixing Volume",
3224 : Constant::Units::m3,
3225 3 : thisZnAirRpt.MixVolume,
3226 : OutputProcessor::TimeStepType::System,
3227 : OutputProcessor::StoreType::Sum,
3228 : zoneName);
3229 6 : SetupOutputVariable(state,
3230 : "Zone Mixing Current Density Volume Flow Rate",
3231 : Constant::Units::m3_s,
3232 3 : thisZnAirRpt.MixVdotCurDensity,
3233 : OutputProcessor::TimeStepType::System,
3234 : OutputProcessor::StoreType::Average,
3235 : zoneName);
3236 6 : SetupOutputVariable(state,
3237 : "Zone Mixing Standard Density Volume Flow Rate",
3238 : Constant::Units::m3_s,
3239 3 : thisZnAirRpt.MixVdotStdDensity,
3240 : OutputProcessor::TimeStepType::System,
3241 : OutputProcessor::StoreType::Average,
3242 : zoneName);
3243 6 : SetupOutputVariable(state,
3244 : "Zone Mixing Mass",
3245 : Constant::Units::kg,
3246 3 : thisZnAirRpt.MixMass,
3247 : OutputProcessor::TimeStepType::System,
3248 : OutputProcessor::StoreType::Sum,
3249 : zoneName);
3250 6 : SetupOutputVariable(state,
3251 : "Zone Mixing Mass Flow Rate",
3252 : Constant::Units::kg_s,
3253 3 : thisZnAirRpt.MixMdot,
3254 : OutputProcessor::TimeStepType::System,
3255 : OutputProcessor::StoreType::Average,
3256 : zoneName);
3257 6 : SetupOutputVariable(state,
3258 : "Zone Mixing Sensible Heat Loss Energy",
3259 : Constant::Units::J,
3260 3 : thisZnAirRpt.MixHeatLoss,
3261 : OutputProcessor::TimeStepType::System,
3262 : OutputProcessor::StoreType::Sum,
3263 : zoneName);
3264 6 : SetupOutputVariable(state,
3265 : "Zone Mixing Sensible Heat Gain Energy",
3266 : Constant::Units::J,
3267 3 : thisZnAirRpt.MixHeatGain,
3268 : OutputProcessor::TimeStepType::System,
3269 : OutputProcessor::StoreType::Sum,
3270 : zoneName);
3271 6 : SetupOutputVariable(state,
3272 : "Zone Mixing Latent Heat Loss Energy",
3273 : Constant::Units::J,
3274 3 : thisZnAirRpt.MixLatentLoss,
3275 : OutputProcessor::TimeStepType::System,
3276 : OutputProcessor::StoreType::Sum,
3277 : zoneName);
3278 6 : SetupOutputVariable(state,
3279 : "Zone Mixing Latent Heat Gain Energy",
3280 : Constant::Units::J,
3281 3 : thisZnAirRpt.MixLatentGain,
3282 : OutputProcessor::TimeStepType::System,
3283 : OutputProcessor::StoreType::Sum,
3284 : zoneName);
3285 6 : SetupOutputVariable(state,
3286 : "Zone Mixing Total Heat Loss Energy",
3287 : Constant::Units::J,
3288 3 : thisZnAirRpt.MixTotalLoss,
3289 : OutputProcessor::TimeStepType::System,
3290 : OutputProcessor::StoreType::Sum,
3291 : zoneName);
3292 6 : SetupOutputVariable(state,
3293 : "Zone Mixing Total Heat Gain Energy",
3294 : Constant::Units::J,
3295 3 : thisZnAirRpt.MixTotalGain,
3296 : OutputProcessor::TimeStepType::System,
3297 : OutputProcessor::StoreType::Sum,
3298 : zoneName);
3299 : }
3300 : }
3301 10 : int fromZoneNum = state.dataHeatBal->CrossMixing(mixingRepNum).FromZone;
3302 10 : if (fromZoneNum > 0) {
3303 10 : if (RepVarSet(fromZoneNum)) {
3304 1 : RepVarSet(fromZoneNum) = false;
3305 1 : std::string const &fromZoneName = state.dataHeatBal->Zone(fromZoneNum).Name;
3306 1 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(fromZoneNum);
3307 2 : SetupOutputVariable(state,
3308 : "Zone Mixing Volume",
3309 : Constant::Units::m3,
3310 1 : thisZnAirRpt.MixVolume,
3311 : OutputProcessor::TimeStepType::System,
3312 : OutputProcessor::StoreType::Sum,
3313 : fromZoneName);
3314 2 : SetupOutputVariable(state,
3315 : "Zone Mixing Current Density Volume Flow Rate",
3316 : Constant::Units::m3_s,
3317 1 : thisZnAirRpt.MixVdotCurDensity,
3318 : OutputProcessor::TimeStepType::System,
3319 : OutputProcessor::StoreType::Average,
3320 : fromZoneName);
3321 2 : SetupOutputVariable(state,
3322 : "Zone Mixing Standard Density Volume Flow Rate",
3323 : Constant::Units::m3_s,
3324 1 : thisZnAirRpt.MixVdotStdDensity,
3325 : OutputProcessor::TimeStepType::System,
3326 : OutputProcessor::StoreType::Average,
3327 : fromZoneName);
3328 2 : SetupOutputVariable(state,
3329 : "Zone Mixing Mass",
3330 : Constant::Units::kg,
3331 1 : thisZnAirRpt.MixMass,
3332 : OutputProcessor::TimeStepType::System,
3333 : OutputProcessor::StoreType::Sum,
3334 : fromZoneName);
3335 2 : SetupOutputVariable(state,
3336 : "Zone Mixing Mass Flow Rate",
3337 : Constant::Units::kg_s,
3338 1 : thisZnAirRpt.MixMdot,
3339 : OutputProcessor::TimeStepType::System,
3340 : OutputProcessor::StoreType::Average,
3341 : fromZoneName);
3342 2 : SetupOutputVariable(state,
3343 : "Zone Mixing Sensible Heat Loss Energy",
3344 : Constant::Units::J,
3345 1 : thisZnAirRpt.MixHeatLoss,
3346 : OutputProcessor::TimeStepType::System,
3347 : OutputProcessor::StoreType::Sum,
3348 : fromZoneName);
3349 2 : SetupOutputVariable(state,
3350 : "Zone Mixing Sensible Heat Gain Energy",
3351 : Constant::Units::J,
3352 1 : thisZnAirRpt.MixHeatGain,
3353 : OutputProcessor::TimeStepType::System,
3354 : OutputProcessor::StoreType::Sum,
3355 : fromZoneName);
3356 2 : SetupOutputVariable(state,
3357 : "Zone Mixing Latent Heat Loss Energy",
3358 : Constant::Units::J,
3359 1 : thisZnAirRpt.MixLatentLoss,
3360 : OutputProcessor::TimeStepType::System,
3361 : OutputProcessor::StoreType::Sum,
3362 : fromZoneName);
3363 2 : SetupOutputVariable(state,
3364 : "Zone Mixing Latent Heat Gain Energy",
3365 : Constant::Units::J,
3366 1 : thisZnAirRpt.MixLatentGain,
3367 : OutputProcessor::TimeStepType::System,
3368 : OutputProcessor::StoreType::Sum,
3369 : fromZoneName);
3370 2 : SetupOutputVariable(state,
3371 : "Zone Mixing Total Heat Loss Energy",
3372 : Constant::Units::J,
3373 1 : thisZnAirRpt.MixTotalLoss,
3374 : OutputProcessor::TimeStepType::System,
3375 : OutputProcessor::StoreType::Sum,
3376 : fromZoneName);
3377 2 : SetupOutputVariable(state,
3378 : "Zone Mixing Total Heat Gain Energy",
3379 : Constant::Units::J,
3380 1 : thisZnAirRpt.MixTotalGain,
3381 : OutputProcessor::TimeStepType::System,
3382 : OutputProcessor::StoreType::Sum,
3383 : fromZoneName);
3384 : }
3385 : }
3386 :
3387 10 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
3388 0 : SetupEMSActuator(state,
3389 : "ZoneCrossMixing",
3390 0 : state.dataHeatBal->CrossMixing(mixingRepNum).Name,
3391 : "Air Exchange Flow Rate",
3392 : "[m3/s]",
3393 0 : state.dataHeatBal->CrossMixing(mixingRepNum).EMSSimpleMixingOn,
3394 0 : state.dataHeatBal->CrossMixing(mixingRepNum).EMSimpleMixingFlowRate);
3395 : }
3396 : }
3397 : }
3398 :
3399 120 : cCurrentModuleObject = "ZoneRefrigerationDoorMixing";
3400 120 : state.dataHeatBal->TotRefDoorMixing = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
3401 120 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
3402 0 : state.dataHeatBal->RefDoorMixing.allocate(state.dataGlobal->NumOfZones);
3403 0 : for (auto &e : state.dataHeatBal->RefDoorMixing)
3404 0 : e.NumRefDoorConnections = 0;
3405 :
3406 0 : for (int Loop = 1; Loop <= state.dataHeatBal->TotRefDoorMixing; ++Loop) {
3407 :
3408 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3409 : cCurrentModuleObject,
3410 : Loop,
3411 : cAlphaArgs,
3412 : NumAlpha,
3413 : rNumericArgs,
3414 : NumNumber,
3415 : IOStat,
3416 : lNumericFieldBlanks,
3417 : lAlphaFieldBlanks,
3418 : cAlphaFieldNames,
3419 : cNumericFieldNames);
3420 :
3421 0 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
3422 0 : NameThisObject = cAlphaArgs(1);
3423 :
3424 0 : int AlphaNum = 2;
3425 0 : int Zone1Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->Zone);
3426 0 : int space1Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->space);
3427 0 : if ((Zone1Num == 0) && (space1Num == 0)) {
3428 0 : ShowSevereError(state,
3429 0 : format("{}{}=\"{}\", invalid (not found) {}=\"{}\".",
3430 : RoutineName,
3431 : cCurrentModuleObject,
3432 : cAlphaArgs(1),
3433 : cAlphaFieldNames(AlphaNum),
3434 : cAlphaArgs(AlphaNum)));
3435 0 : ErrorsFound = true;
3436 0 : } else if (Zone1Num == 0) {
3437 0 : Zone1Num = state.dataHeatBal->space(space1Num).zoneNum;
3438 : }
3439 :
3440 0 : ++AlphaNum; // 3
3441 0 : int Zone2Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->Zone);
3442 0 : int space2Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->space);
3443 0 : if ((Zone2Num == 0) && (space2Num == 0)) {
3444 0 : ShowSevereError(state,
3445 0 : format("{}{}=\"{}\", invalid (not found) {}=\"{}\".",
3446 : RoutineName,
3447 : cCurrentModuleObject,
3448 : cAlphaArgs(1),
3449 : cAlphaFieldNames(AlphaNum),
3450 : cAlphaArgs(AlphaNum)));
3451 0 : ErrorsFound = true;
3452 0 : } else if (Zone2Num == 0) {
3453 0 : Zone2Num = state.dataHeatBal->space(space2Num).zoneNum;
3454 : }
3455 :
3456 0 : int spaceNumA = 0;
3457 0 : int spaceNumB = 0;
3458 0 : if (Zone1Num == Zone2Num) {
3459 0 : ShowSevereError(state,
3460 0 : format("{}{}=\"{}\", The same zone name has been entered for both sides of a refrigerated door {}=\"{}\".",
3461 : RoutineName,
3462 : cCurrentModuleObject,
3463 : cAlphaArgs(1),
3464 : cAlphaFieldNames(AlphaNum),
3465 : cAlphaArgs(AlphaNum)));
3466 0 : ErrorsFound = true;
3467 0 : } else if (Zone1Num < Zone2Num) { // zone 1 will come first in soln loop, id zone 2 as mate zone
3468 0 : ZoneNumA = Zone1Num;
3469 0 : ZoneNumB = Zone2Num;
3470 0 : spaceNumA = space1Num;
3471 0 : spaceNumB = space2Num;
3472 : } else { // zone 2 will come first in soln loop, id zone 1 as mate zone
3473 0 : ZoneNumA = Zone2Num;
3474 0 : ZoneNumB = Zone1Num;
3475 0 : spaceNumA = space2Num;
3476 0 : spaceNumB = space1Num;
3477 : }
3478 :
3479 0 : auto &zoneA = state.dataHeatBal->RefDoorMixing(ZoneNumA);
3480 0 : auto &zoneB = state.dataHeatBal->RefDoorMixing(ZoneNumB);
3481 :
3482 0 : if (!allocated(zoneA.openScheds)) {
3483 0 : zoneA.DoorMixingObjectName.allocate(state.dataGlobal->NumOfZones);
3484 0 : zoneA.openScheds.allocate(state.dataGlobal->NumOfZones);
3485 0 : zoneA.DoorHeight.allocate(state.dataGlobal->NumOfZones);
3486 0 : zoneA.DoorArea.allocate(state.dataGlobal->NumOfZones);
3487 0 : zoneA.Protection.allocate(state.dataGlobal->NumOfZones);
3488 0 : zoneA.MateZonePtr.allocate(state.dataGlobal->NumOfZones);
3489 0 : zoneA.EMSRefDoorMixingOn.allocate(state.dataGlobal->NumOfZones);
3490 0 : zoneA.EMSRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3491 0 : zoneA.VolRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3492 0 : zoneA.DoorProtTypeName.allocate(state.dataGlobal->NumOfZones);
3493 0 : zoneA.DoorMixingObjectName = "";
3494 0 : zoneA.openScheds = nullptr;
3495 0 : zoneA.DoorHeight = 0.0;
3496 0 : zoneA.DoorArea = 0.0;
3497 0 : zoneA.Protection = RefDoorNone;
3498 0 : zoneA.MateZonePtr = 0;
3499 0 : zoneA.EMSRefDoorMixingOn = false;
3500 0 : zoneA.EMSRefDoorFlowRate = 0.0;
3501 0 : zoneA.VolRefDoorFlowRate = 0.0;
3502 0 : zoneA.DoorProtTypeName = "";
3503 : } // First refrigeration mixing in this zone
3504 :
3505 0 : if (!allocated(zoneB.openScheds)) {
3506 0 : zoneB.DoorMixingObjectName.allocate(state.dataGlobal->NumOfZones);
3507 0 : zoneB.openScheds.allocate(state.dataGlobal->NumOfZones);
3508 0 : zoneB.DoorHeight.allocate(state.dataGlobal->NumOfZones);
3509 0 : zoneB.DoorArea.allocate(state.dataGlobal->NumOfZones);
3510 0 : zoneB.Protection.allocate(state.dataGlobal->NumOfZones);
3511 0 : zoneB.MateZonePtr.allocate(state.dataGlobal->NumOfZones);
3512 0 : zoneB.EMSRefDoorMixingOn.allocate(state.dataGlobal->NumOfZones);
3513 0 : zoneB.EMSRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3514 0 : zoneB.VolRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3515 0 : zoneB.DoorProtTypeName.allocate(state.dataGlobal->NumOfZones);
3516 0 : zoneB.DoorMixingObjectName = "";
3517 0 : zoneB.openScheds = nullptr;
3518 0 : zoneB.DoorHeight = 0.0;
3519 0 : zoneB.DoorArea = 0.0;
3520 0 : zoneB.Protection = RefDoorNone;
3521 0 : zoneB.MateZonePtr = 0;
3522 0 : zoneB.EMSRefDoorMixingOn = false;
3523 0 : zoneB.EMSRefDoorFlowRate = 0.0;
3524 0 : zoneB.VolRefDoorFlowRate = 0.0;
3525 0 : zoneB.DoorProtTypeName = "";
3526 : } // First refrigeration mixing in this zone
3527 :
3528 0 : ConnectionNumber = zoneA.NumRefDoorConnections + 1;
3529 0 : zoneA.NumRefDoorConnections = ConnectionNumber;
3530 0 : zoneA.ZonePtr = ZoneNumA;
3531 0 : zoneA.spaceIndex = spaceNumA;
3532 0 : zoneA.fromSpaceIndex = spaceNumB;
3533 0 : zoneA.MateZonePtr(ConnectionNumber) = ZoneNumB;
3534 0 : zoneA.DoorMixingObjectName(ConnectionNumber) = NameThisObject;
3535 : // need to make sure same pair of zones is only entered once.
3536 0 : if (zoneA.RefDoorMixFlag && zoneB.RefDoorMixFlag) {
3537 0 : if (zoneA.NumRefDoorConnections > 1) {
3538 0 : for (int ConnectTest = 1; ConnectTest <= (ConnectionNumber - 1); ++ConnectTest) {
3539 0 : if (zoneA.MateZonePtr(ConnectTest) != zoneA.MateZonePtr(ConnectionNumber)) continue;
3540 0 : ShowSevereError(
3541 : state,
3542 0 : format("{}{}=\"{}\", and {}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), zoneA.DoorMixingObjectName(ConnectTest)));
3543 0 : ShowContinueError(state,
3544 0 : format(" Share same pair of zones: \"{}\" and \"{}\". Only one RefrigerationDoorMixing object is allowed "
3545 : "for any unique pair of zones.",
3546 0 : state.dataHeatBal->Zone(ZoneNumA).Name,
3547 0 : state.dataHeatBal->Zone(ZoneNumB).Name));
3548 0 : ErrorsFound = true;
3549 : } // ConnectTest
3550 : } // NumRefDoorconnections > 1
3551 0 : } else { // Both zones need to be flagged with ref doors
3552 0 : zoneA.RefDoorMixFlag = true;
3553 0 : zoneB.RefDoorMixFlag = true;
3554 : } // Both zones already flagged with ref doors
3555 :
3556 0 : ++AlphaNum; // 4
3557 0 : if (lAlphaFieldBlanks(AlphaNum)) {
3558 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(AlphaNum));
3559 0 : ErrorsFound = true;
3560 0 : } else if ((zoneA.openScheds(ConnectionNumber) = Sched::GetSchedule(state, cAlphaArgs(AlphaNum))) == nullptr) {
3561 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(AlphaNum), cAlphaArgs(AlphaNum));
3562 0 : ErrorsFound = true;
3563 0 : } else if (!zoneA.openScheds(ConnectionNumber)->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
3564 0 : Sched::ShowSevereBadMinMax(state, eoh, cAlphaFieldNames(AlphaNum), cAlphaArgs(AlphaNum), Clusive::In, 0.0, Clusive::In, 1.0);
3565 0 : ErrorsFound = true;
3566 : } //(lAlphaFieldBlanks(AlphaNum)) THEN
3567 :
3568 0 : int NumbNum = 1;
3569 0 : if (lAlphaFieldBlanks(NumbNum)) {
3570 0 : zoneA.DoorHeight(ConnectionNumber) = 3.0; // default height of 3 meters
3571 0 : ShowWarningError(state,
3572 0 : format("{}{}=\"{}{} is blank and the default value of 3.0 will be used.",
3573 : RoutineName,
3574 : cCurrentModuleObject,
3575 : cAlphaArgs(1),
3576 : cNumericFieldNames(NumbNum)));
3577 : } else {
3578 0 : zoneA.DoorHeight(ConnectionNumber) = rNumericArgs(NumbNum);
3579 0 : if ((zoneA.DoorHeight(ConnectionNumber) < 0) || (zoneA.DoorHeight(ConnectionNumber) > 50.0)) {
3580 0 : ShowSevereError(
3581 : state,
3582 0 : format("{}{} = {} must have a door height between 0 and 50 meters. ", RoutineName, cCurrentModuleObject, cAlphaArgs(1)));
3583 0 : ErrorsFound = true;
3584 : }
3585 : }
3586 :
3587 0 : ++NumbNum; // 2
3588 0 : if (lAlphaFieldBlanks(NumbNum)) {
3589 0 : zoneA.DoorArea(ConnectionNumber) = 9.0; // default area of 9 m2
3590 0 : ShowWarningError(state,
3591 0 : format("{}{}=\"{}{} is blank and the default value of 9 m2 will be used.",
3592 : RoutineName,
3593 : cCurrentModuleObject,
3594 : cAlphaArgs(1),
3595 : cNumericFieldNames(NumbNum)));
3596 : } else {
3597 0 : zoneA.DoorArea(ConnectionNumber) = rNumericArgs(NumbNum);
3598 0 : if ((zoneA.DoorArea(ConnectionNumber) < 0) || (zoneA.DoorArea(ConnectionNumber) > 400.0)) {
3599 0 : ShowSevereError(
3600 : state,
3601 0 : format(
3602 : "{}{} = {} must have a door height between 0 and 400 square meters. ", RoutineName, cCurrentModuleObject, cAlphaArgs(1)));
3603 0 : ErrorsFound = true;
3604 : }
3605 : }
3606 :
3607 0 : ++AlphaNum; // 5
3608 : // Door protection type.
3609 0 : if (lAlphaFieldBlanks(AlphaNum)) {
3610 0 : zoneA.Protection(ConnectionNumber) = RefDoorNone; // Default
3611 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "None"; // Default
3612 0 : ShowWarningError(state,
3613 0 : format("{}{}=\"{}\" {} is blank. Default of no door protection will be used",
3614 : RoutineName,
3615 : cCurrentModuleObject,
3616 : cAlphaArgs(1),
3617 : cAlphaFieldNames(AlphaNum)));
3618 : } else {
3619 0 : if (cAlphaArgs(AlphaNum) == "NONE") {
3620 0 : zoneA.Protection(ConnectionNumber) = RefDoorNone;
3621 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "None";
3622 0 : } else if (cAlphaArgs(AlphaNum) == "AIRCURTAIN") {
3623 0 : zoneA.Protection(ConnectionNumber) = RefDoorAirCurtain;
3624 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "AirCurtain";
3625 0 : } else if (cAlphaArgs(AlphaNum) == "STRIPCURTAIN") {
3626 0 : zoneA.Protection(ConnectionNumber) = RefDoorStripCurtain;
3627 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "StripCurtain";
3628 : } else {
3629 0 : ShowSevereError(state,
3630 0 : format("{}{}=\"{}\", invalid calculation method={} with alphanum of 5: {}",
3631 : RoutineName,
3632 : cCurrentModuleObject,
3633 : cAlphaArgs(1),
3634 : cAlphaArgs(AlphaNum),
3635 : cAlphaArgs(5)));
3636 0 : ErrorsFound = true;
3637 : } // =none, etc.
3638 : } // Blank
3639 :
3640 0 : if (ZoneNumA > 0) {
3641 0 : if (RepVarSet(ZoneNumA)) {
3642 0 : RepVarSet(ZoneNumA) = false;
3643 0 : SetupOutputVariable(state,
3644 : "Zone Mixing Volume",
3645 : Constant::Units::m3,
3646 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixVolume,
3647 : OutputProcessor::TimeStepType::System,
3648 : OutputProcessor::StoreType::Sum,
3649 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3650 0 : SetupOutputVariable(state,
3651 : "Zone Mixing Current Density Volume Flow Rate",
3652 : Constant::Units::m3_s,
3653 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixVdotCurDensity,
3654 : OutputProcessor::TimeStepType::System,
3655 : OutputProcessor::StoreType::Average,
3656 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3657 0 : SetupOutputVariable(state,
3658 : "Zone Mixing Standard Density Volume Flow Rate",
3659 : Constant::Units::m3_s,
3660 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixVdotStdDensity,
3661 : OutputProcessor::TimeStepType::System,
3662 : OutputProcessor::StoreType::Average,
3663 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3664 0 : SetupOutputVariable(state,
3665 : "Zone Mixing Mass",
3666 : Constant::Units::kg,
3667 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixMass,
3668 : OutputProcessor::TimeStepType::System,
3669 : OutputProcessor::StoreType::Sum,
3670 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3671 0 : SetupOutputVariable(state,
3672 : "Zone Mixing Mass Flow Rate",
3673 : Constant::Units::kg_s,
3674 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixMdot,
3675 : OutputProcessor::TimeStepType::System,
3676 : OutputProcessor::StoreType::Average,
3677 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3678 0 : SetupOutputVariable(state,
3679 : "Zone Mixing Sensible Heat Loss Energy",
3680 : Constant::Units::J,
3681 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixHeatLoss,
3682 : OutputProcessor::TimeStepType::System,
3683 : OutputProcessor::StoreType::Sum,
3684 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3685 0 : SetupOutputVariable(state,
3686 : "Zone Mixing Sensible Heat Gain Energy",
3687 : Constant::Units::J,
3688 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixHeatGain,
3689 : OutputProcessor::TimeStepType::System,
3690 : OutputProcessor::StoreType::Sum,
3691 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3692 0 : SetupOutputVariable(state,
3693 : "Zone Mixing Latent Heat Loss Energy",
3694 : Constant::Units::J,
3695 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixLatentLoss,
3696 : OutputProcessor::TimeStepType::System,
3697 : OutputProcessor::StoreType::Sum,
3698 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3699 0 : SetupOutputVariable(state,
3700 : "Zone Mixing Latent Heat Gain Energy",
3701 : Constant::Units::J,
3702 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixLatentGain,
3703 : OutputProcessor::TimeStepType::System,
3704 : OutputProcessor::StoreType::Sum,
3705 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3706 0 : SetupOutputVariable(state,
3707 : "Zone Mixing Total Heat Loss Energy",
3708 : Constant::Units::J,
3709 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixTotalLoss,
3710 : OutputProcessor::TimeStepType::System,
3711 : OutputProcessor::StoreType::Sum,
3712 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3713 0 : SetupOutputVariable(state,
3714 : "Zone Mixing Total Heat Gain Energy",
3715 : Constant::Units::J,
3716 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixTotalGain,
3717 : OutputProcessor::TimeStepType::System,
3718 : OutputProcessor::StoreType::Sum,
3719 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3720 : }
3721 : }
3722 0 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
3723 0 : SetupEMSActuator(state,
3724 : "ZoneRefDoorMixing",
3725 : zoneA.Name,
3726 : "Air Exchange Flow Rate",
3727 : "[m3/s]",
3728 : zoneA.EMSRefDoorMixingOn(ConnectionNumber),
3729 0 : zoneA.EMSRefDoorFlowRate(ConnectionNumber));
3730 : }
3731 :
3732 0 : if (ZoneNumB > 0) {
3733 0 : if (RepVarSet(ZoneNumB)) {
3734 0 : RepVarSet(ZoneNumB) = false;
3735 0 : SetupOutputVariable(state,
3736 : "Zone Mixing Volume",
3737 : Constant::Units::m3,
3738 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixVolume,
3739 : OutputProcessor::TimeStepType::System,
3740 : OutputProcessor::StoreType::Sum,
3741 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3742 0 : SetupOutputVariable(state,
3743 : "Zone Mixing Current Density Volume Flow Rate",
3744 : Constant::Units::m3_s,
3745 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixVdotCurDensity,
3746 : OutputProcessor::TimeStepType::System,
3747 : OutputProcessor::StoreType::Average,
3748 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3749 0 : SetupOutputVariable(state,
3750 : "Zone Mixing Standard Density Volume Flow Rate",
3751 : Constant::Units::m3_s,
3752 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixVdotStdDensity,
3753 : OutputProcessor::TimeStepType::System,
3754 : OutputProcessor::StoreType::Average,
3755 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3756 0 : SetupOutputVariable(state,
3757 : "Zone Mixing Mass",
3758 : Constant::Units::kg,
3759 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixMass,
3760 : OutputProcessor::TimeStepType::System,
3761 : OutputProcessor::StoreType::Sum,
3762 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3763 0 : SetupOutputVariable(state,
3764 : "Zone Mixing Mass Flow Rate",
3765 : Constant::Units::kg_s,
3766 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixMdot,
3767 : OutputProcessor::TimeStepType::System,
3768 : OutputProcessor::StoreType::Average,
3769 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3770 0 : SetupOutputVariable(state,
3771 : "Zone Mixing Sensible Heat Loss Energy",
3772 : Constant::Units::J,
3773 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixHeatLoss,
3774 : OutputProcessor::TimeStepType::System,
3775 : OutputProcessor::StoreType::Sum,
3776 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3777 0 : SetupOutputVariable(state,
3778 : "Zone Mixing Sensible Heat Gain Energy",
3779 : Constant::Units::J,
3780 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixHeatGain,
3781 : OutputProcessor::TimeStepType::System,
3782 : OutputProcessor::StoreType::Sum,
3783 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3784 0 : SetupOutputVariable(state,
3785 : "Zone Mixing Latent Heat Loss Energy",
3786 : Constant::Units::J,
3787 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixLatentLoss,
3788 : OutputProcessor::TimeStepType::System,
3789 : OutputProcessor::StoreType::Sum,
3790 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3791 0 : SetupOutputVariable(state,
3792 : "Zone Mixing Latent Heat Gain Energy",
3793 : Constant::Units::J,
3794 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixLatentGain,
3795 : OutputProcessor::TimeStepType::System,
3796 : OutputProcessor::StoreType::Sum,
3797 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3798 0 : SetupOutputVariable(state,
3799 : "Zone Mixing Total Heat Loss Energy",
3800 : Constant::Units::J,
3801 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixTotalLoss,
3802 : OutputProcessor::TimeStepType::System,
3803 : OutputProcessor::StoreType::Sum,
3804 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3805 0 : SetupOutputVariable(state,
3806 : "Zone Mixing Total Heat Gain Energy",
3807 : Constant::Units::J,
3808 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixTotalGain,
3809 : OutputProcessor::TimeStepType::System,
3810 : OutputProcessor::StoreType::Sum,
3811 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3812 : }
3813 : }
3814 0 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
3815 0 : SetupEMSActuator(state,
3816 : "ZoneRefDoorMixing",
3817 : zoneB.Name,
3818 : "Air Exchange Flow Rate",
3819 : "[m3/s]",
3820 : zoneA.EMSRefDoorMixingOn(ConnectionNumber),
3821 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).EMSRefDoorFlowRate(ConnectionNumber));
3822 : }
3823 : } // DO Loop=1,TotRefDoorMixing
3824 : } // TotRefDoorMixing > 0)
3825 :
3826 120 : RepVarSet.deallocate();
3827 120 : cAlphaArgs.deallocate();
3828 120 : cAlphaFieldNames.deallocate();
3829 120 : cNumericFieldNames.deallocate();
3830 120 : rNumericArgs.deallocate();
3831 120 : lAlphaFieldBlanks.deallocate();
3832 120 : lNumericFieldBlanks.deallocate();
3833 :
3834 120 : TotInfilVentFlow.dimension(state.dataGlobal->NumOfZones, 0.0);
3835 :
3836 255 : auto divide_and_print_if_greater_than_zero = [&](const Real64 denominator, const Real64 numerator) {
3837 255 : if (denominator > 0.0) {
3838 143 : print(state.files.eio, "{:.3R},", numerator / denominator);
3839 : } else {
3840 112 : print(state.files.eio, "N/A,");
3841 : }
3842 255 : };
3843 :
3844 171 : for (int Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
3845 51 : if (Loop == 1)
3846 21 : print(state.files.eio,
3847 : Format_721,
3848 : "ZoneInfiltration",
3849 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/Exterior Surface Area {m3/s-m2},ACH - "
3850 : "Air Changes per Hour,Equation A - Constant Term Coefficient {},Equation B - Temperature Term Coefficient {1/C},Equation C - "
3851 : "Velocity Term Coefficient {s/m}, Equation D - Velocity Squared Term Coefficient {s2/m2}");
3852 :
3853 51 : int ZoneNum = state.dataHeatBal->Infiltration(Loop).ZonePtr;
3854 51 : if (ZoneNum == 0) {
3855 0 : print(state.files.eio, Format_722, "Infiltration-Illegal Zone specified", state.dataHeatBal->Infiltration(Loop).Name);
3856 0 : continue;
3857 : }
3858 51 : TotInfilVentFlow(ZoneNum) += state.dataHeatBal->Infiltration(Loop).DesignLevel;
3859 51 : print(state.files.eio,
3860 : Format_720,
3861 : "ZoneInfiltration",
3862 51 : state.dataHeatBal->Infiltration(Loop).Name,
3863 51 : state.dataHeatBal->Infiltration(Loop).sched->Name,
3864 51 : state.dataHeatBal->Zone(ZoneNum).Name,
3865 51 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
3866 51 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
3867 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).DesignLevel);
3868 :
3869 51 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->Infiltration(Loop).DesignLevel);
3870 51 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).ExteriorTotalSurfArea,
3871 51 : state.dataHeatBal->Infiltration(Loop).DesignLevel);
3872 51 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
3873 51 : state.dataHeatBal->Infiltration(Loop).DesignLevel * Constant::rSecsInHour);
3874 :
3875 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).ConstantTermCoef);
3876 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).TemperatureTermCoef);
3877 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).VelocityTermCoef);
3878 51 : print(state.files.eio, "{:.3R}\n", state.dataHeatBal->Infiltration(Loop).VelocitySQTermCoef);
3879 : }
3880 :
3881 120 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
3882 19 : for (int Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
3883 11 : int ZoneNum = state.dataHeatBal->Infiltration(Loop).ZonePtr;
3884 11 : state.dataHeatBal->MassConservation(ZoneNum).InfiltrationPtr = Loop;
3885 : }
3886 : }
3887 :
3888 130 : for (int Loop = 1; Loop <= state.dataHeatBal->TotVentilation; ++Loop) {
3889 10 : if (Loop == 1) {
3890 1 : print(state.files.eio,
3891 : Format_721,
3892 : "ZoneVentilation",
3893 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/person Area {m3/s-person},ACH - Air "
3894 : "Changes per Hour,Fan Type {Exhaust;Intake;Natural},Fan Pressure Rise {Pa},Fan Efficiency {},Equation A - Constant Term "
3895 : "Coefficient {},Equation B - Temperature Term Coefficient {1/C},Equation C - Velocity Term Coefficient {s/m}, Equation D - "
3896 : "Velocity Squared Term Coefficient {s2/m2},Minimum Indoor Temperature{C}/Schedule,Maximum Indoor "
3897 : "Temperature{C}/Schedule,Delta Temperature{C}/Schedule,Minimum Outdoor Temperature{C}/Schedule,Maximum Outdoor "
3898 : "Temperature{C}/Schedule,Maximum WindSpeed{m/s}");
3899 : }
3900 :
3901 10 : int ZoneNum = state.dataHeatBal->Ventilation(Loop).ZonePtr;
3902 10 : if (ZoneNum == 0) {
3903 0 : print(state.files.eio, Format_722, "Ventilation-Illegal Zone specified", state.dataHeatBal->Ventilation(Loop).Name);
3904 0 : continue;
3905 : }
3906 10 : TotInfilVentFlow(ZoneNum) += state.dataHeatBal->Ventilation(Loop).DesignLevel;
3907 10 : print(state.files.eio,
3908 : Format_720,
3909 : "ZoneVentilation",
3910 10 : state.dataHeatBal->Ventilation(Loop).Name,
3911 10 : state.dataHeatBal->Ventilation(Loop).availSched->Name,
3912 10 : state.dataHeatBal->Zone(ZoneNum).Name,
3913 10 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
3914 10 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
3915 :
3916 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).DesignLevel);
3917 :
3918 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->Ventilation(Loop).DesignLevel);
3919 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).TotOccupants, state.dataHeatBal->Ventilation(Loop).DesignLevel);
3920 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
3921 10 : state.dataHeatBal->Ventilation(Loop).DesignLevel * Constant::rSecsInHour);
3922 :
3923 10 : if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Exhaust) {
3924 0 : print(state.files.eio, "Exhaust,");
3925 10 : } else if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Intake) {
3926 0 : print(state.files.eio, "Intake,");
3927 10 : } else if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Natural) {
3928 10 : print(state.files.eio, "Natural,");
3929 0 : } else if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Balanced) {
3930 0 : print(state.files.eio, "Balanced,");
3931 : } else {
3932 0 : print(state.files.eio, "UNKNOWN,");
3933 : }
3934 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).FanPressure);
3935 10 : print(state.files.eio, "{:.1R},", state.dataHeatBal->Ventilation(Loop).FanEfficiency);
3936 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).ConstantTermCoef);
3937 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).TemperatureTermCoef);
3938 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).VelocityTermCoef);
3939 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).VelocitySQTermCoef);
3940 :
3941 : // TODO Should this also be prefixed with "Schedule: " like the following ones are?
3942 10 : if (state.dataHeatBal->Ventilation(Loop).minIndoorTempSched != nullptr) {
3943 0 : print(state.files.eio, "{},", state.dataHeatBal->Ventilation(Loop).minIndoorTempSched->Name);
3944 : } else {
3945 10 : print(state.files.eio, "{:.2R},", state.dataHeatBal->Ventilation(Loop).MinIndoorTemperature);
3946 : }
3947 :
3948 40 : const auto print_temperature = [&](Sched::Schedule const *ptr, const Real64 value) {
3949 40 : if (ptr != nullptr) {
3950 0 : print(state.files.eio, "Schedule: {},", ptr->Name);
3951 : } else {
3952 40 : print(state.files.eio, "{:.2R},", value);
3953 : }
3954 40 : };
3955 :
3956 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).maxIndoorTempSched, state.dataHeatBal->Ventilation(Loop).MaxIndoorTemperature);
3957 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).deltaTempSched, state.dataHeatBal->Ventilation(Loop).DelTemperature);
3958 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).minOutdoorTempSched, state.dataHeatBal->Ventilation(Loop).MinOutdoorTemperature);
3959 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).maxOutdoorTempSched, state.dataHeatBal->Ventilation(Loop).MaxOutdoorTemperature);
3960 :
3961 10 : print(state.files.eio, "{:.2R}\n", state.dataHeatBal->Ventilation(Loop).MaxWindSpeed);
3962 : }
3963 :
3964 120 : TotMixingFlow.dimension(state.dataGlobal->NumOfZones, 0.0);
3965 134 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
3966 14 : if (Loop == 1)
3967 8 : print(state.files.eio,
3968 : Format_721,
3969 : "Mixing",
3970 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/person Area {m3/s-person},ACH - Air "
3971 : "Changes per Hour,From/Source Zone,Delta Temperature {C}");
3972 :
3973 14 : int ZoneNum = state.dataHeatBal->Mixing(Loop).ZonePtr;
3974 14 : if (ZoneNum == 0) {
3975 0 : print(state.files.eio, Format_722, "Mixing-Illegal Zone specified", state.dataHeatBal->Mixing(Loop).Name);
3976 0 : continue;
3977 : }
3978 14 : TotMixingFlow(ZoneNum) += state.dataHeatBal->Mixing(Loop).DesignLevel;
3979 14 : print(state.files.eio,
3980 : Format_720,
3981 : "Mixing",
3982 14 : state.dataHeatBal->Mixing(Loop).Name,
3983 14 : state.dataHeatBal->Mixing(Loop).sched->Name,
3984 14 : state.dataHeatBal->Zone(ZoneNum).Name,
3985 14 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
3986 14 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
3987 14 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Mixing(Loop).DesignLevel);
3988 14 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->Mixing(Loop).DesignLevel);
3989 14 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).TotOccupants, state.dataHeatBal->Mixing(Loop).DesignLevel);
3990 14 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
3991 14 : state.dataHeatBal->Mixing(Loop).DesignLevel * Constant::rSecsInHour);
3992 :
3993 14 : print(state.files.eio, "{},", state.dataHeatBal->Zone(state.dataHeatBal->Mixing(Loop).FromZone).Name);
3994 14 : print(state.files.eio, "{:.2R}\n", state.dataHeatBal->Mixing(Loop).DeltaTemperature);
3995 : }
3996 :
3997 130 : for (int Loop = 1; Loop <= state.dataHeatBal->TotCrossMixing; ++Loop) {
3998 10 : if (Loop == 1) {
3999 2 : print(state.files.eio,
4000 : Format_721,
4001 : "CrossMixing",
4002 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/person Area {m3/s-person},ACH - Air "
4003 : "Changes per Hour,From/Source Zone,Delta Temperature {C}");
4004 : }
4005 :
4006 10 : int ZoneNum = state.dataHeatBal->CrossMixing(Loop).ZonePtr;
4007 10 : if (ZoneNum == 0) {
4008 0 : print(state.files.eio, Format_722, "CrossMixing-Illegal Zone specified", state.dataHeatBal->CrossMixing(Loop).Name);
4009 0 : continue;
4010 : }
4011 10 : TotMixingFlow(ZoneNum) += state.dataHeatBal->CrossMixing(Loop).DesignLevel;
4012 10 : print(state.files.eio,
4013 : Format_720,
4014 : "CrossMixing",
4015 10 : state.dataHeatBal->CrossMixing(Loop).Name,
4016 10 : state.dataHeatBal->CrossMixing(Loop).sched->Name,
4017 10 : state.dataHeatBal->Zone(ZoneNum).Name,
4018 10 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
4019 10 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
4020 :
4021 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->CrossMixing(Loop).DesignLevel);
4022 :
4023 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->CrossMixing(Loop).DesignLevel);
4024 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).TotOccupants, state.dataHeatBal->CrossMixing(Loop).DesignLevel);
4025 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
4026 10 : state.dataHeatBal->CrossMixing(Loop).DesignLevel * Constant::rSecsInHour);
4027 :
4028 10 : print(state.files.eio, "{},", state.dataHeatBal->Zone(state.dataHeatBal->CrossMixing(Loop).FromZone).Name);
4029 10 : print(state.files.eio, "{:.2R}\n", state.dataHeatBal->CrossMixing(Loop).DeltaTemperature);
4030 : }
4031 :
4032 120 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
4033 : static constexpr std::string_view Format_724("! <{} Airflow Stats Nominal>, {}\n");
4034 0 : print(state.files.eio,
4035 : Format_724,
4036 : "RefrigerationDoorMixing ",
4037 : "Name, Zone 1 Name,Zone 2 Name,Door Opening Schedule Name,Door Height {m},Door Area {m2},Door Protection Type");
4038 0 : for (ZoneNumA = 1; ZoneNumA <= (state.dataGlobal->NumOfZones - 1); ++ZoneNumA) {
4039 0 : if (!state.dataHeatBal->RefDoorMixing(ZoneNumA).RefDoorMixFlag) continue;
4040 0 : for (ConnectionNumber = 1; ConnectionNumber <= state.dataHeatBal->RefDoorMixing(ZoneNumA).NumRefDoorConnections; ++ConnectionNumber) {
4041 0 : ZoneNumB = state.dataHeatBal->RefDoorMixing(ZoneNumA).MateZonePtr(ConnectionNumber);
4042 : // TotMixingFlow(ZoneNum)=TotMixingFlow(ZoneNum)+RefDoorMixing(Loop)%!DesignLevel
4043 : static constexpr std::string_view Format_723(" {} Airflow Stats Nominal, {},{},{},{},{:.3R},{:.3R},{}\n");
4044 0 : print(state.files.eio,
4045 : Format_723,
4046 : "RefrigerationDoorMixing",
4047 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorMixingObjectName(ConnectionNumber),
4048 0 : state.dataHeatBal->Zone(ZoneNumA).Name,
4049 0 : state.dataHeatBal->Zone(ZoneNumB).Name,
4050 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).openScheds(ConnectionNumber)->Name,
4051 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorHeight(ConnectionNumber),
4052 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorArea(ConnectionNumber),
4053 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorProtTypeName(ConnectionNumber));
4054 : } // ConnectionNumber
4055 : } // ZoneNumA
4056 : } //(TotRefDoorMixing .GT. 0)
4057 :
4058 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4059 163 : state.dataHeatBal->Zone(ZoneNum).NominalInfilVent = TotInfilVentFlow(ZoneNum);
4060 163 : state.dataHeatBal->Zone(ZoneNum).NominalMixing = TotMixingFlow(ZoneNum);
4061 : }
4062 :
4063 120 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
4064 : // Check for infiltration in zone which are only a mixing source zone
4065 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4066 18 : if ((state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing &&
4067 24 : state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone) &&
4068 6 : (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment != DataHeatBalance::InfiltrationFlow::No)) {
4069 5 : if (state.dataHeatBal->MassConservation(ZoneNum).InfiltrationPtr == 0) {
4070 0 : ShowSevereError(
4071 0 : state, format("{}: Infiltration object is not defined for zone = {}", RoutineName, state.dataHeatBal->Zone(ZoneNum).Name));
4072 0 : ShowContinueError(state, "Zone air mass flow balance requires infiltration object for source zones of mixing objects");
4073 : }
4074 : }
4075 : }
4076 : // Set up zone air mass balance output variables
4077 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4078 36 : SetupOutputVariable(state,
4079 : "Zone Air Mass Balance Supply Mass Flow Rate",
4080 : Constant::Units::kg_s,
4081 18 : state.dataHeatBal->MassConservation(ZoneNum).InMassFlowRate,
4082 : OutputProcessor::TimeStepType::System,
4083 : OutputProcessor::StoreType::Average,
4084 18 : state.dataHeatBal->Zone(ZoneNum).Name);
4085 36 : SetupOutputVariable(state,
4086 : "Zone Air Mass Balance Exhaust Mass Flow Rate",
4087 : Constant::Units::kg_s,
4088 18 : state.dataHeatBal->MassConservation(ZoneNum).ExhMassFlowRate,
4089 : OutputProcessor::TimeStepType::System,
4090 : OutputProcessor::StoreType::Average,
4091 18 : state.dataHeatBal->Zone(ZoneNum).Name);
4092 36 : SetupOutputVariable(state,
4093 : "Zone Air Mass Balance Return Mass Flow Rate",
4094 : Constant::Units::kg_s,
4095 18 : state.dataHeatBal->MassConservation(ZoneNum).RetMassFlowRate,
4096 : OutputProcessor::TimeStepType::System,
4097 : OutputProcessor::StoreType::Average,
4098 18 : state.dataHeatBal->Zone(ZoneNum).Name);
4099 34 : if ((state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) &&
4100 16 : ((state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject +
4101 16 : state.dataHeatBal->MassConservation(ZoneNum).NumReceivingZonesMixingObject) > 0)) {
4102 28 : SetupOutputVariable(state,
4103 : "Zone Air Mass Balance Mixing Receiving Mass Flow Rate",
4104 : Constant::Units::kg_s,
4105 14 : state.dataHeatBal->MassConservation(ZoneNum).MixingMassFlowRate,
4106 : OutputProcessor::TimeStepType::System,
4107 : OutputProcessor::StoreType::Average,
4108 14 : state.dataHeatBal->Zone(ZoneNum).Name);
4109 28 : SetupOutputVariable(state,
4110 : "Zone Air Mass Balance Mixing Source Mass Flow Rate",
4111 : Constant::Units::kg_s,
4112 14 : state.dataHeatBal->MassConservation(ZoneNum).MixingSourceMassFlowRate,
4113 : OutputProcessor::TimeStepType::System,
4114 : OutputProcessor::StoreType::Average,
4115 14 : state.dataHeatBal->Zone(ZoneNum).Name);
4116 : }
4117 18 : if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment != DataHeatBalance::InfiltrationFlow::No) {
4118 15 : if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationForZones == DataHeatBalance::InfiltrationZoneType::AllZones ||
4119 0 : (state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject > 0)) {
4120 15 : if (state.dataHeatBal->MassConservation(ZoneNum).InfiltrationPtr > 0) {
4121 22 : SetupOutputVariable(state,
4122 : "Zone Air Mass Balance Infiltration Mass Flow Rate",
4123 : Constant::Units::kg_s,
4124 11 : state.dataHeatBal->MassConservation(ZoneNum).InfiltrationMassFlowRate,
4125 : OutputProcessor::TimeStepType::System,
4126 : OutputProcessor::StoreType::Average,
4127 11 : state.dataHeatBal->Zone(ZoneNum).Name);
4128 11 : SetupOutputVariable(state,
4129 : "Zone Air Mass Balance Infiltration Status",
4130 : Constant::Units::None,
4131 11 : state.dataHeatBal->MassConservation(ZoneNum).IncludeInfilToZoneMassBal,
4132 : OutputProcessor::TimeStepType::System,
4133 : OutputProcessor::StoreType::Average,
4134 11 : state.dataHeatBal->Zone(ZoneNum).Name);
4135 : }
4136 : }
4137 : }
4138 : }
4139 : }
4140 :
4141 120 : TotInfilVentFlow.deallocate();
4142 120 : TotMixingFlow.deallocate();
4143 : // ' Area per Occupant {m2/person}, Occupant per Area {person/m2}, Interior Lighting {W/m2}, ', &
4144 : // 'Electric Load {W/m2}, Gas Load {W/m2}, Other Load {W/m2}, Hot Water Eq {W/m2}, Outdoor Controlled Baseboard Heat')
4145 120 : }
4146 :
4147 106 : void GetRoomAirModelParameters(EnergyPlusData &state, bool &errFlag) // True if errors found during this input routine
4148 : {
4149 :
4150 : // SUBROUTINE INFORMATION:
4151 : // AUTHOR Brent Griffith
4152 : // DATE WRITTEN August 2001
4153 : // RE-ENGINEERED April 2003, Weixiu Kong
4154 : // December 2003, CC
4155 :
4156 : // PURPOSE OF THIS SUBROUTINE:
4157 : // Get room air model parameters for all zones at once
4158 :
4159 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4160 : int NumAlphas; // States which alpha value to read from a
4161 : // "Number" line
4162 : int NumNumbers; // Number of numbers encountered
4163 : int Status; // Notes if there was an error in processing the input
4164 : int AirModelNum;
4165 : int NumOfAirModels;
4166 : int ZoneNum;
4167 : bool IsNotOK;
4168 :
4169 : // Initialize default values for air model parameters
4170 106 : state.dataRoomAir->AirModel.allocate(state.dataGlobal->NumOfZones);
4171 :
4172 106 : bool ErrorsFound = false;
4173 106 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
4174 :
4175 106 : cCurrentModuleObject = "RoomAirModelType";
4176 106 : NumOfAirModels = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
4177 106 : if (NumOfAirModels > state.dataGlobal->NumOfZones) {
4178 0 : ShowSevereError(state, format("Too many {}. Cannot exceed the number of Zones.", cCurrentModuleObject));
4179 0 : ErrorsFound = true;
4180 : }
4181 106 : if (NumOfAirModels > 0) {
4182 2 : state.dataRoomAir->IsZoneDispVent3Node.dimension(state.dataGlobal->NumOfZones, false);
4183 2 : state.dataRoomAir->IsZoneCrossVent.dimension(state.dataGlobal->NumOfZones, false);
4184 2 : state.dataRoomAir->IsZoneUFAD.dimension(state.dataGlobal->NumOfZones, false);
4185 : }
4186 :
4187 109 : for (AirModelNum = 1; AirModelNum <= NumOfAirModels; ++AirModelNum) {
4188 9 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
4189 : cCurrentModuleObject,
4190 : AirModelNum,
4191 3 : state.dataIPShortCut->cAlphaArgs,
4192 : NumAlphas,
4193 3 : state.dataIPShortCut->rNumericArgs,
4194 : NumNumbers,
4195 : Status,
4196 : _,
4197 : _,
4198 3 : state.dataIPShortCut->cAlphaFieldNames,
4199 3 : state.dataIPShortCut->cNumericFieldNames);
4200 3 : ZoneNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
4201 3 : if (ZoneNum != 0) {
4202 3 : if (!state.dataRoomAir->AirModel(ZoneNum).Name.empty()) {
4203 0 : ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
4204 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4205 0 : ShowContinueError(state, "Duplicate zone name, only one type of roomair model is allowed per zone");
4206 0 : ShowContinueError(state,
4207 0 : format("Zone {} was already assigned a roomair model by {} = {}",
4208 0 : state.dataIPShortCut->cAlphaArgs(2),
4209 : cCurrentModuleObject,
4210 0 : roomAirModelNamesUC[(int)state.dataRoomAir->AirModel(ZoneNum).AirModel]));
4211 0 : ShowContinueError(
4212 : state,
4213 0 : format("Air Model Type for zone already set to {}", roomAirModelNamesUC[(int)state.dataRoomAir->AirModel(ZoneNum).AirModel]));
4214 0 : ShowContinueError(state, format("Trying to overwrite with model type = {}", state.dataIPShortCut->cAlphaArgs(3)));
4215 0 : ErrorsFound = true;
4216 : }
4217 3 : state.dataRoomAir->AirModel(ZoneNum).ZoneName = state.dataIPShortCut->cAlphaArgs(2);
4218 :
4219 : // state.dataRoomAir->AirModel(ZoneNum).AirModelName = state.dataIPShortCut->cAlphaArgs(1);
4220 3 : state.dataRoomAir->AirModel(ZoneNum).AirModel =
4221 3 : static_cast<RoomAir::RoomAirModel>(getEnumValue(roomAirModelNamesUC, state.dataIPShortCut->cAlphaArgs(3))); // is this arg1 or arg3?
4222 3 : switch (state.dataRoomAir->AirModel(ZoneNum).AirModel) {
4223 0 : case RoomAir::RoomAirModel::Mixing:
4224 : // nothing to do here actually
4225 0 : break;
4226 :
4227 0 : case RoomAir::RoomAirModel::DispVent1Node:
4228 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4229 0 : state.dataRoomAir->DispVent1NodeModelUsed = true;
4230 0 : IsNotOK = false;
4231 0 : ValidateComponent(state,
4232 : "RoomAirSettings:OneNodeDisplacementVentilation",
4233 : "zone_name",
4234 0 : state.dataIPShortCut->cAlphaArgs(2),
4235 : IsNotOK,
4236 : "GetRoomAirModelParameters");
4237 0 : if (IsNotOK) {
4238 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4239 0 : ErrorsFound = true;
4240 : }
4241 0 : break;
4242 :
4243 0 : case RoomAir::RoomAirModel::DispVent3Node:
4244 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4245 0 : state.dataRoomAir->UCSDModelUsed = true;
4246 0 : IsNotOK = false;
4247 0 : ValidateComponent(state,
4248 : "RoomAirSettings:ThreeNodeDisplacementVentilation",
4249 : "zone_name",
4250 0 : state.dataIPShortCut->cAlphaArgs(2),
4251 : IsNotOK,
4252 : "GetRoomAirModelParameters");
4253 0 : if (IsNotOK) {
4254 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4255 0 : ErrorsFound = true;
4256 : }
4257 0 : break;
4258 :
4259 0 : case RoomAir::RoomAirModel::CrossVent:
4260 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4261 0 : state.dataRoomAir->UCSDModelUsed = true;
4262 0 : IsNotOK = false;
4263 0 : ValidateComponent(state,
4264 : "RoomAirSettings:CrossVentilation",
4265 : "zone_name",
4266 0 : state.dataIPShortCut->cAlphaArgs(2),
4267 : IsNotOK,
4268 : "GetRoomAirModelParameters");
4269 0 : if (IsNotOK) {
4270 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4271 0 : ErrorsFound = true;
4272 : }
4273 0 : break;
4274 :
4275 0 : case RoomAir::RoomAirModel::UFADInt:
4276 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4277 0 : state.dataRoomAir->UCSDModelUsed = true;
4278 0 : ValidateComponent(state,
4279 : "RoomAirSettings:UnderFloorAirDistributionInterior",
4280 : "zone_name",
4281 0 : state.dataIPShortCut->cAlphaArgs(2),
4282 : IsNotOK,
4283 : "GetRoomAirModelParameters");
4284 0 : if (IsNotOK) {
4285 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4286 0 : ErrorsFound = true;
4287 : }
4288 0 : break;
4289 :
4290 0 : case RoomAir::RoomAirModel::UFADExt:
4291 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4292 0 : state.dataRoomAir->UCSDModelUsed = true;
4293 0 : ValidateComponent(state,
4294 : "RoomAirSettings:UnderFloorAirDistributionExterior",
4295 : "zone_name",
4296 0 : state.dataIPShortCut->cAlphaArgs(2),
4297 : IsNotOK,
4298 : "GetRoomAirModelParameters");
4299 0 : if (IsNotOK) {
4300 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4301 0 : ErrorsFound = true;
4302 : }
4303 0 : break;
4304 :
4305 0 : case RoomAir::RoomAirModel::UserDefined:
4306 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4307 0 : state.dataRoomAir->UserDefinedUsed = true;
4308 0 : break;
4309 :
4310 3 : case RoomAir::RoomAirModel::AirflowNetwork:
4311 3 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4312 3 : if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirflowNetwork:SimulationControl") == 0) {
4313 4 : ShowSevereError(state,
4314 6 : format("In {} = {}: {} = AIRFLOWNETWORK.",
4315 : cCurrentModuleObject,
4316 2 : state.dataIPShortCut->cAlphaArgs(1),
4317 2 : state.dataIPShortCut->cAlphaFieldNames(3)));
4318 4 : ShowContinueError(state,
4319 : "This model requires AirflowNetwork:* objects to form a complete network, including "
4320 : "AirflowNetwork:Intrazone:Node and AirflowNetwork:Intrazone:Linkage.");
4321 4 : ShowContinueError(state, "AirflowNetwork:SimulationControl not found.");
4322 2 : ErrorsFound = true;
4323 : }
4324 3 : break;
4325 :
4326 0 : default:
4327 0 : ShowWarningError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
4328 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4329 0 : ShowContinueError(state, format("The mixing air model will be used for Zone ={}", state.dataIPShortCut->cAlphaArgs(2)));
4330 0 : state.dataRoomAir->AirModel(ZoneNum).AirModel = RoomAir::RoomAirModel::Mixing;
4331 : }
4332 :
4333 3 : state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme =
4334 3 : static_cast<RoomAir::CouplingScheme>(getEnumValue(couplingSchemeNamesUC, state.dataIPShortCut->cAlphaArgs(4)));
4335 3 : if (state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme == RoomAir::CouplingScheme::Invalid) {
4336 0 : ShowWarningError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4)));
4337 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4338 0 : ShowContinueError(state, format("The direct coupling scheme will be used for Zone ={}", state.dataIPShortCut->cAlphaArgs(2)));
4339 0 : state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme = RoomAir::CouplingScheme::Direct;
4340 : }
4341 :
4342 : } else { // Zone Not Found
4343 0 : ShowSevereError(state, format("{}, Zone not found={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(2)));
4344 0 : ShowContinueError(state, format("occurs in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4345 0 : ErrorsFound = true;
4346 : }
4347 : } // AirModel_Param_Loop
4348 :
4349 242 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4350 : // this used to be an if (NumOfAirModels == 0) block, but both the IF and the ELSE had the same content, these two lines:
4351 136 : state.dataRoomAir->AirModel(ZoneNum).Name = "MIXING AIR MODEL FOR " + state.dataHeatBal->Zone(ZoneNum).Name;
4352 136 : state.dataRoomAir->AirModel(ZoneNum).ZoneName = state.dataHeatBal->Zone(ZoneNum).Name;
4353 : // set global flag for non-mixing model
4354 136 : if (state.dataRoomAir->AirModel(ZoneNum).AirModel != RoomAir::RoomAirModel::Mixing) {
4355 3 : state.dataRoomAir->anyNonMixingRoomAirModel = true;
4356 : }
4357 : }
4358 :
4359 106 : if (state.dataRoomAir->anyNonMixingRoomAirModel) {
4360 2 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
4361 0 : ShowSevereError(state, "Non-Mixing RoomAirModelType is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
4362 0 : ErrorsFound = true;
4363 : }
4364 : }
4365 :
4366 : // Write RoomAir Model details onto EIO file
4367 : static constexpr std::string_view RoomAirHeader("! <RoomAir Model>, Zone Name, Mixing/Mundt/UCSDDV/UCSDCV/UCSDUFI/UCSDUFE/User Defined\n");
4368 106 : print(state.files.eio, RoomAirHeader);
4369 242 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4370 : static constexpr std::array<std::string_view, (int)RoomAir::RoomAirModel::Num> roomAirModelStrings = {"UserDefined",
4371 : "Mixing/Well-Stirred",
4372 : "OneNodeDisplacementVentilation",
4373 : "ThreeNodeDisplacementVentilation",
4374 : "CrossVentilation",
4375 : "UnderFloorAirDistributionInterior",
4376 : "UnderFloorAirDistributionExterior",
4377 : "AirflowNetwork"};
4378 :
4379 136 : print(state.files.eio,
4380 : "RoomAir Model,{},{}\n",
4381 136 : state.dataHeatBal->Zone(ZoneNum).Name,
4382 136 : roomAirModelStrings[(int)state.dataRoomAir->AirModel(ZoneNum).AirModel]);
4383 : }
4384 :
4385 106 : if (ErrorsFound) {
4386 1 : ShowSevereError(state, format("Errors found in processing input for {}", cCurrentModuleObject));
4387 1 : errFlag = true;
4388 : }
4389 106 : }
4390 :
4391 249951 : void InitAirHeatBalance(EnergyPlusData &state)
4392 : {
4393 :
4394 : // SUBROUTINE INFORMATION:
4395 : // AUTHOR Richard J. Liesen
4396 : // DATE WRITTEN February 1998
4397 :
4398 : // PURPOSE OF THIS SUBROUTINE:
4399 : // This subroutine is for initializations within the
4400 : // air heat balance.
4401 :
4402 : // Do the following initializations (every time step):
4403 249951 : InitSimpleMixingConvectiveHeatGains(state);
4404 249951 : }
4405 :
4406 249955 : void InitSimpleMixingConvectiveHeatGains(EnergyPlusData &state)
4407 : {
4408 : // SUBROUTINE INFORMATION:
4409 : // AUTHOR Richard Liesen
4410 : // DATE WRITTEN February 1998
4411 : // MODIFIED March 2003, FCW: allow individual window/door venting control
4412 : // DATE MODIFIED April 2000
4413 : // May 2009, Brent Griffith added EMS override to mixing and cross mixing flows
4414 : // renamed routine and did some cleanup
4415 : // August 2011, Therese Stovall added refrigeration door mixing flows
4416 :
4417 : // PURPOSE OF THIS SUBROUTINE:
4418 : // This subroutine sets up the mixing and cross mixing flows
4419 :
4420 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4421 : Real64 ZoneMixingFlowSum; // sum of zone mixing flows for a zone
4422 :
4423 : // Select type of airflow calculation
4424 249955 : if (state.dataHeatBal->AirFlowFlag) { // Simplified airflow calculation
4425 : // Process the scheduled Mixing for air heat balance
4426 255741 : for (auto &thisMixing : state.dataHeatBal->Mixing) {
4427 5787 : thisMixing.DesiredAirFlowRate = thisMixing.DesignLevel * thisMixing.sched->getCurrentVal();
4428 5787 : if (thisMixing.EMSSimpleMixingOn) thisMixing.DesiredAirFlowRate = thisMixing.EMSimpleMixingFlowRate;
4429 5787 : thisMixing.DesiredAirFlowRateSaved = thisMixing.DesiredAirFlowRate;
4430 : }
4431 :
4432 : // if zone air mass flow balance enforced calculate the fraction of
4433 : // contribution of each mixing object to a zone mixed flow rate, BAN Feb 2014
4434 249954 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
4435 22 : for (auto &massConservZone : state.dataHeatBal->MassConservation) {
4436 15 : ZoneMixingFlowSum = 0.0;
4437 15 : int NumOfMixingObjects = massConservZone.NumReceivingZonesMixingObject;
4438 25 : for (int Loop = 1; Loop <= NumOfMixingObjects; ++Loop) {
4439 10 : ZoneMixingFlowSum += state.dataHeatBal->Mixing(Loop).DesignLevel;
4440 10 : massConservZone.ZoneMixingReceivingFr(Loop) = 0.0;
4441 : }
4442 15 : if (ZoneMixingFlowSum > 0.0) {
4443 15 : for (int Loop = 1; Loop <= NumOfMixingObjects; ++Loop) {
4444 8 : massConservZone.ZoneMixingReceivingFr(Loop) = state.dataHeatBal->Mixing(Loop).DesignLevel / ZoneMixingFlowSum;
4445 : }
4446 : }
4447 : }
4448 : }
4449 :
4450 : // Process the scheduled CrossMixing for air heat balance
4451 255734 : for (auto &thisCrossMix : state.dataHeatBal->CrossMixing) {
4452 5780 : thisCrossMix.DesiredAirFlowRate = thisCrossMix.DesignLevel * thisCrossMix.sched->getCurrentVal();
4453 5780 : if (thisCrossMix.EMSSimpleMixingOn) thisCrossMix.DesiredAirFlowRate = thisCrossMix.EMSimpleMixingFlowRate;
4454 : }
4455 :
4456 : // Note - do each Pair a Single time, so must do increment reports for both zones
4457 : // Can't have a pair that has ZoneA zone number = NumOfZones because organized
4458 : // in input with lowest zone # first no matter how input in idf
4459 :
4460 : // Process the scheduled Refrigeration Door mixing for air heat balance
4461 249954 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
4462 0 : for (int NZ = 1; NZ <= (state.dataGlobal->NumOfZones - 1);
4463 : ++NZ) { // Can't have %ZonePtr==NumOfZones because lesser zone # of pair placed in ZonePtr in input
4464 0 : auto &thisRefDoor = state.dataHeatBal->RefDoorMixing(NZ);
4465 0 : if (!thisRefDoor.RefDoorMixFlag) continue;
4466 0 : if (thisRefDoor.ZonePtr == NZ) {
4467 0 : for (int J = 1; J <= thisRefDoor.NumRefDoorConnections; ++J) {
4468 0 : thisRefDoor.VolRefDoorFlowRate(J) = 0.0;
4469 0 : if (thisRefDoor.EMSRefDoorMixingOn(J)) thisRefDoor.VolRefDoorFlowRate(J) = thisRefDoor.EMSRefDoorFlowRate(J);
4470 : }
4471 : }
4472 : }
4473 : } // TotRefDoorMixing
4474 :
4475 : // Infiltration and ventilation calculations have been moved to a subroutine of CalcAirFlowSimple in HVAC Manager
4476 : }
4477 249955 : }
4478 :
4479 249946 : void CalcHeatBalanceAir(EnergyPlusData &state)
4480 : {
4481 :
4482 : // PURPOSE OF THIS SUBROUTINE:
4483 : // This subroutine calculates the air component of the heat balance.
4484 :
4485 249946 : if (state.dataGlobal->externalHVACManager) {
4486 1353 : if (!state.dataGlobal->externalHVACManagerInitialized) {
4487 1353 : initializeForExternalHVACManager(state);
4488 : }
4489 1353 : state.dataGlobal->externalHVACManager(&state);
4490 : } else {
4491 248593 : HVACManager::ManageHVAC(state);
4492 : }
4493 249945 : }
4494 :
4495 : // END Algorithm Section of the Module
4496 :
4497 1353 : void initializeForExternalHVACManager(EnergyPlusData &state)
4498 : {
4499 : // this function will ultimately provide a nice series of calls that initialize all the hvac stuff needed
4500 : // to allow an external hvac manager to play nice with E+
4501 1353 : EnergyPlus::ZoneTempPredictorCorrector::InitZoneAirSetPoints(state);
4502 1353 : }
4503 :
4504 249945 : void ReportZoneMeanAirTemp(EnergyPlusData &state)
4505 : {
4506 : // SUBROUTINE INFORMATION:
4507 : // AUTHOR Linda Lawrie
4508 : // DATE WRITTEN July 2000
4509 :
4510 : // PURPOSE OF THIS SUBROUTINE:
4511 : // This subroutine updates the report variables for the AirHeatBalance.
4512 249945 : if (state.dataHeatBalAirMgr->CalcExtraReportVarMyOneTimeFlag) {
4513 572 : for (auto const *reqVar : state.dataOutputProcessor->reqVars) {
4514 469 : if (reqVar->name == "ZONE WETBULB GLOBE TEMPERATURE") {
4515 21 : if (reqVar->key.empty()) {
4516 0 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
4517 0 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(ZoneLoop);
4518 0 : thisZnAirRpt.ReportWBGT = true;
4519 : }
4520 : } else {
4521 21 : int ZoneLoop = Util::FindItemInList(Util::makeUPPER(reqVar->key), state.dataHeatBal->Zone);
4522 21 : if (ZoneLoop > 0) {
4523 21 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(ZoneLoop);
4524 21 : thisZnAirRpt.ReportWBGT = true;
4525 : }
4526 : }
4527 448 : } else if (reqVar->name == "SPACE WETBULB GLOBE TEMPERATURE") {
4528 0 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
4529 0 : if (reqVar->key.empty()) {
4530 0 : for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
4531 0 : auto &thisSpaceAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
4532 0 : thisSpaceAirRpt.ReportWBGT = true;
4533 : }
4534 : } else {
4535 0 : int spaceNum = Util::FindItemInList(Util::makeUPPER(reqVar->key), state.dataHeatBal->space);
4536 0 : if (spaceNum > 0) {
4537 0 : auto &thisSpaceAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
4538 0 : thisSpaceAirRpt.ReportWBGT = true;
4539 : }
4540 : }
4541 : }
4542 : }
4543 : }
4544 :
4545 : // EMS sensor request WBGT check
4546 108 : for (int loop = 1; loop <= state.dataRuntimeLang->NumSensors; ++loop) {
4547 5 : if (state.dataRuntimeLang->Sensor(loop).OutputVarName == "ZONE WETBULB GLOBE TEMPERATURE") {
4548 0 : int ZoneLoop = Util::FindItemInList(state.dataRuntimeLang->Sensor(loop).UniqueKeyName, state.dataHeatBal->Zone);
4549 0 : if (ZoneLoop > 0) {
4550 0 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(ZoneLoop);
4551 0 : thisZnAirRpt.ReportWBGT = true;
4552 : }
4553 5 : } else if (state.dataRuntimeLang->Sensor(loop).OutputVarName == "SPACE WETBULB GLOBE TEMPERATURE") {
4554 0 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
4555 0 : int spaceNum = Util::FindItemInList(state.dataRuntimeLang->Sensor(loop).UniqueKeyName, state.dataHeatBal->space);
4556 0 : if (spaceNum > 0) {
4557 0 : auto &thisSpaceAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
4558 0 : thisSpaceAirRpt.ReportWBGT = true;
4559 : }
4560 : }
4561 : }
4562 : }
4563 103 : state.dataHeatBalAirMgr->CalcExtraReportVarMyOneTimeFlag = false;
4564 : }
4565 586584 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
4566 336639 : auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop);
4567 336639 : calcMeanAirTemps(state, thisZoneHB.ZTAV, thisZoneHB.airHumRatAvg, thisZoneHB.MRT, state.dataHeatBal->ZnAirRpt(ZoneLoop), ZoneLoop);
4568 336639 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
4569 5775 : for (int spaceNum : state.dataHeatBal->Zone(ZoneLoop).spaceIndexes) {
4570 3465 : auto const &thisSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum);
4571 3465 : calcMeanAirTemps(
4572 6930 : state, thisSpaceHB.ZTAV, thisSpaceHB.airHumRatAvg, thisSpaceHB.MRT, state.dataHeatBal->spaceAirRpt(spaceNum), ZoneLoop);
4573 : }
4574 : }
4575 : }
4576 249945 : }
4577 :
4578 340104 : void calcMeanAirTemps(EnergyPlusData &state,
4579 : Real64 const ZTAV,
4580 : Real64 const airHumRatAvg,
4581 : Real64 const MRT,
4582 : DataHeatBalance::AirReportVars &thisAirRpt,
4583 : int const zoneNum)
4584 : {
4585 : // The mean air temperature is actually ZTAV which is the average
4586 : // temperature of the air temperatures at the system time step for the
4587 : // entire zone time step.
4588 340104 : thisAirRpt.MeanAirTemp = ZTAV;
4589 340104 : thisAirRpt.MeanAirHumRat = airHumRatAvg;
4590 340104 : thisAirRpt.OperativeTemp = 0.5 * (ZTAV + MRT);
4591 340104 : thisAirRpt.MeanAirDewPointTemp = Psychrometrics::PsyTdpFnWPb(state, thisAirRpt.MeanAirHumRat, state.dataEnvrn->OutBaroPress);
4592 :
4593 : // if operative temperature control is being used, then radiative fraction/weighting
4594 : // might be defined by user to be something different than 0.5, even scheduled over simulation period
4595 340104 : if (state.dataZoneCtrls->AnyOpTempControl) { // dig further...
4596 : // find TempControlledZoneID from ZoneLoop index
4597 0 : int TempControlledZoneID = state.dataHeatBal->Zone(zoneNum).TempControlledZoneIndex;
4598 0 : if (state.dataHeatBal->Zone(zoneNum).IsControlled) {
4599 0 : if ((state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).OpTempCtrl != DataZoneControls::TempCtrl::None)) {
4600 : Real64 thisMRTFraction; // temp working value for radiative fraction/weight
4601 : // is operative temp radiative fraction scheduled or fixed?
4602 0 : if (state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).OpTempCtrl == DataZoneControls::TempCtrl::Scheduled) {
4603 0 : thisMRTFraction = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).opTempRadiativeFractionSched->getCurrentVal();
4604 : } else {
4605 0 : thisMRTFraction = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).FixedRadiativeFraction;
4606 : }
4607 0 : thisAirRpt.OperativeTemp = 0.5 * (ZTAV + MRT);
4608 0 : thisAirRpt.ThermOperativeTemp = (1.0 - thisMRTFraction) * ZTAV + thisMRTFraction * MRT;
4609 : }
4610 : }
4611 : }
4612 340104 : if (thisAirRpt.ReportWBGT) {
4613 : // note that the WetBulbTemp here is for temporary verification, it will not be another added reporting variable
4614 72565 : thisAirRpt.WetbulbGlobeTemp =
4615 72565 : 0.7 * Psychrometrics::PsyTwbFnTdbWPb(state, ZTAV, airHumRatAvg, state.dataEnvrn->OutBaroPress) + 0.3 * thisAirRpt.OperativeTemp;
4616 : }
4617 340104 : }
4618 :
4619 : } // namespace EnergyPlus::HeatBalanceAirManager
|