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 2 : }
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 :
2617 : // Min indoor temp
2618 14 : if (NumAlpha > 6) {
2619 0 : if (lAlphaFieldBlanks(7)) {
2620 : // Is this an error or is there a default?
2621 0 : } else if ((thisMixing.minIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(7))) == nullptr) {
2622 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(7), cAlphaArgs(7));
2623 0 : ErrorsFound = true;
2624 0 : } else if (!thisMixing.minIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2625 0 : Sched::ShowSevereBadMinMax(
2626 0 : state, eoh, cAlphaFieldNames(7), cAlphaArgs(7), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2627 0 : ErrorsFound = true;
2628 : }
2629 : }
2630 :
2631 : // Max indoor temp
2632 14 : if (NumAlpha > 7) {
2633 0 : if (lAlphaFieldBlanks(8)) {
2634 0 : } else if ((thisMixing.maxIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(8))) == nullptr) {
2635 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8));
2636 0 : ErrorsFound = true;
2637 0 : } else if (!thisMixing.maxIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2638 0 : Sched::ShowSevereBadMinMax(
2639 0 : state, eoh, cAlphaFieldNames(8), cAlphaArgs(8), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2640 0 : ErrorsFound = true;
2641 : }
2642 : }
2643 :
2644 : // Min source temp
2645 14 : if (NumAlpha > 8) {
2646 0 : if (lAlphaFieldBlanks(9)) {
2647 0 : } else if ((thisMixing.minSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(9))) == nullptr) {
2648 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(9), cAlphaArgs(9));
2649 0 : ErrorsFound = true;
2650 0 : } else if (!thisMixing.minSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2651 0 : Sched::ShowSevereBadMinMax(
2652 0 : state, eoh, cAlphaFieldNames(9), cAlphaArgs(9), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2653 0 : ErrorsFound = true;
2654 : }
2655 : }
2656 :
2657 : // Max source temp
2658 14 : if (NumAlpha > 9) {
2659 0 : if (lAlphaFieldBlanks(10)) {
2660 0 : } else if ((thisMixing.maxSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(10))) == nullptr) {
2661 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(10), cAlphaArgs(10));
2662 0 : ErrorsFound = true;
2663 0 : } else if (!thisMixing.maxSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2664 0 : Sched::ShowSevereBadMinMax(
2665 0 : state, eoh, cAlphaFieldNames(10), cAlphaArgs(10), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2666 0 : ErrorsFound = true;
2667 : }
2668 : }
2669 :
2670 14 : if (NumAlpha > 10) {
2671 0 : if (lAlphaFieldBlanks(11)) {
2672 0 : } else if ((thisMixing.minOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(11))) == nullptr) {
2673 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(11), cAlphaArgs(11));
2674 0 : ErrorsFound = true;
2675 0 : } else if (!thisMixing.minOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2676 0 : Sched::ShowSevereBadMinMax(
2677 0 : state, eoh, cAlphaFieldNames(11), cAlphaArgs(11), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2678 0 : ErrorsFound = true;
2679 : }
2680 : }
2681 :
2682 : //
2683 14 : if (NumAlpha > 11) {
2684 0 : if (lAlphaFieldBlanks(12)) {
2685 0 : } else if ((thisMixing.maxOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(12))) == nullptr) {
2686 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(12), cAlphaArgs(12));
2687 0 : ErrorsFound = true;
2688 0 : } else if (!thisMixing.maxOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
2689 0 : Sched::ShowSevereBadMinMax(
2690 0 : state, eoh, cAlphaFieldNames(12), cAlphaArgs(12), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
2691 0 : ErrorsFound = true;
2692 : }
2693 : }
2694 :
2695 14 : if (thisMixing.ZonePtr > 0) {
2696 14 : if (RepVarSet(thisMixing.ZonePtr)) {
2697 11 : RepVarSet(thisMixing.ZonePtr) = false;
2698 22 : SetupOutputVariable(state,
2699 : "Zone Mixing Volume",
2700 : Constant::Units::m3,
2701 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixVolume,
2702 : OutputProcessor::TimeStepType::System,
2703 : OutputProcessor::StoreType::Sum,
2704 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2705 22 : SetupOutputVariable(state,
2706 : "Zone Mixing Current Density Volume Flow Rate",
2707 : Constant::Units::m3_s,
2708 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixVdotCurDensity,
2709 : OutputProcessor::TimeStepType::System,
2710 : OutputProcessor::StoreType::Average,
2711 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2712 22 : SetupOutputVariable(state,
2713 : "Zone Mixing Standard Density Volume Flow Rate",
2714 : Constant::Units::m3_s,
2715 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixVdotStdDensity,
2716 : OutputProcessor::TimeStepType::System,
2717 : OutputProcessor::StoreType::Average,
2718 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2719 22 : SetupOutputVariable(state,
2720 : "Zone Mixing Mass",
2721 : Constant::Units::kg,
2722 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixMass,
2723 : OutputProcessor::TimeStepType::System,
2724 : OutputProcessor::StoreType::Sum,
2725 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2726 22 : SetupOutputVariable(state,
2727 : "Zone Mixing Mass Flow Rate",
2728 : Constant::Units::kg_s,
2729 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixMdot,
2730 : OutputProcessor::TimeStepType::System,
2731 : OutputProcessor::StoreType::Average,
2732 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2733 22 : SetupOutputVariable(state,
2734 : "Zone Mixing Sensible Heat Loss Energy",
2735 : Constant::Units::J,
2736 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixHeatLoss,
2737 : OutputProcessor::TimeStepType::System,
2738 : OutputProcessor::StoreType::Sum,
2739 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2740 22 : SetupOutputVariable(state,
2741 : "Zone Mixing Sensible Heat Gain Energy",
2742 : Constant::Units::J,
2743 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixHeatGain,
2744 : OutputProcessor::TimeStepType::System,
2745 : OutputProcessor::StoreType::Sum,
2746 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2747 22 : SetupOutputVariable(state,
2748 : "Zone Mixing Latent Heat Loss Energy",
2749 : Constant::Units::J,
2750 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixLatentLoss,
2751 : OutputProcessor::TimeStepType::System,
2752 : OutputProcessor::StoreType::Sum,
2753 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2754 22 : SetupOutputVariable(state,
2755 : "Zone Mixing Latent Heat Gain Energy",
2756 : Constant::Units::J,
2757 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixLatentGain,
2758 : OutputProcessor::TimeStepType::System,
2759 : OutputProcessor::StoreType::Sum,
2760 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2761 22 : SetupOutputVariable(state,
2762 : "Zone Mixing Total Heat Loss Energy",
2763 : Constant::Units::J,
2764 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixTotalLoss,
2765 : OutputProcessor::TimeStepType::System,
2766 : OutputProcessor::StoreType::Sum,
2767 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2768 22 : SetupOutputVariable(state,
2769 : "Zone Mixing Total Heat Gain Energy",
2770 : Constant::Units::J,
2771 11 : state.dataHeatBal->ZnAirRpt(thisMixing.ZonePtr).MixTotalGain,
2772 : OutputProcessor::TimeStepType::System,
2773 : OutputProcessor::StoreType::Sum,
2774 11 : state.dataHeatBal->Zone(thisMixing.ZonePtr).Name);
2775 : }
2776 : }
2777 14 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
2778 0 : SetupEMSActuator(state,
2779 : "ZoneMixing",
2780 : thisMixing.Name,
2781 : "Air Exchange Flow Rate",
2782 : "[m3/s]",
2783 0 : thisMixing.EMSSimpleMixingOn,
2784 0 : thisMixing.EMSimpleMixingFlowRate);
2785 : }
2786 : }
2787 : }
2788 : }
2789 :
2790 : // allocate MassConservation
2791 120 : state.dataHeatBal->MassConservation.allocate(state.dataGlobal->NumOfZones);
2792 :
2793 : // added by BAN, 02/14
2794 120 : if (state.dataHeatBal->TotMixing > 0) {
2795 8 : ZoneMixingNum.allocate(state.dataHeatBal->TotMixing);
2796 : // get source zones mixing objects index
2797 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2798 18 : int SourceCount = 0;
2799 50 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
2800 32 : if (ZoneNum == state.dataHeatBal->Mixing(Loop).FromZone) {
2801 14 : SourceCount += 1;
2802 14 : ZoneMixingNum(SourceCount) = Loop;
2803 : }
2804 : }
2805 : // save mixing objects index for zones which serve as a source zone
2806 18 : state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject = SourceCount;
2807 18 : if (SourceCount > 0) {
2808 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingSourcesPtr.allocate(SourceCount);
2809 25 : for (int Loop = 1; Loop <= SourceCount; ++Loop) {
2810 14 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingSourcesPtr(Loop) = ZoneMixingNum(Loop);
2811 : }
2812 : }
2813 : }
2814 :
2815 : // check zones which are used only as a source zones
2816 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2817 50 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
2818 32 : if (ZoneNum != state.dataHeatBal->Mixing(Loop).FromZone) {
2819 18 : continue;
2820 : }
2821 14 : state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone = true;
2822 35 : for (int Loop1 = 1; Loop1 <= state.dataHeatBal->TotMixing; ++Loop1) {
2823 28 : if (ZoneNum == state.dataHeatBal->Mixing(Loop1).ZonePtr) {
2824 7 : state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone = false;
2825 7 : break;
2826 : }
2827 : }
2828 : }
2829 : }
2830 : // get receiving zones mixing objects index
2831 8 : ZoneMixingNum = 0;
2832 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2833 18 : int ReceivingCount = 0;
2834 50 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
2835 32 : if (ZoneNum == state.dataHeatBal->Mixing(Loop).ZonePtr) {
2836 14 : ReceivingCount += 1;
2837 14 : ZoneMixingNum(ReceivingCount) = Loop;
2838 : }
2839 : }
2840 : // save mixing objects index for zones which serve as a receiving zone
2841 18 : state.dataHeatBal->MassConservation(ZoneNum).NumReceivingZonesMixingObject = ReceivingCount;
2842 18 : if (ReceivingCount > 0) {
2843 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingPtr.allocate(ReceivingCount);
2844 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingFr.allocate(ReceivingCount);
2845 11 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingFr = 0.0;
2846 25 : for (int Loop = 1; Loop <= ReceivingCount; ++Loop) {
2847 14 : state.dataHeatBal->MassConservation(ZoneNum).ZoneMixingReceivingPtr(Loop) = ZoneMixingNum(Loop);
2848 : }
2849 : }
2850 : // flag zones used as both source and receiving zone
2851 29 : if (state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject > 0 &&
2852 11 : state.dataHeatBal->MassConservation(ZoneNum).NumReceivingZonesMixingObject > 0) {
2853 4 : state.dataHeatBal->MassConservation(ZoneNum).IsSourceAndReceivingZone = true;
2854 : }
2855 : }
2856 8 : if (allocated(ZoneMixingNum)) {
2857 8 : ZoneMixingNum.deallocate();
2858 : }
2859 : }
2860 :
2861 : // zone mass conservation calculation order starts with receiving zones
2862 : // and then proceeds to source zones
2863 120 : int Loop2 = 0;
2864 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2865 319 : if (!state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone &&
2866 156 : !state.dataHeatBal->MassConservation(ZoneNum).IsSourceAndReceivingZone) {
2867 152 : Loop2 += 1;
2868 152 : state.dataHeatBalFanSys->ZoneReOrder(Loop2) = ZoneNum;
2869 : }
2870 : }
2871 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2872 163 : if (state.dataHeatBal->MassConservation(ZoneNum).IsSourceAndReceivingZone) {
2873 4 : Loop2 += 1;
2874 4 : state.dataHeatBalFanSys->ZoneReOrder(Loop2) = ZoneNum;
2875 : }
2876 : }
2877 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2878 163 : if (state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone) {
2879 7 : Loop2 += 1;
2880 7 : state.dataHeatBalFanSys->ZoneReOrder(Loop2) = ZoneNum;
2881 : }
2882 : }
2883 :
2884 120 : cCurrentModuleObject = "ZoneCrossMixing";
2885 120 : int numZoneCrossMixingInputObjects = 0;
2886 120 : int totZoneCrossMixing = 0; // Total ZoneCrossMixing instances after expansion to spaces
2887 240 : EPVector<InternalHeatGains::GlobalInternalGainMiscObject> zoneCrossMixingInputObjects;
2888 120 : InternalHeatGains::setupIHGZonesAndSpaces(state,
2889 : cCurrentModuleObject,
2890 : zoneCrossMixingInputObjects,
2891 : numZoneCrossMixingInputObjects,
2892 : totZoneCrossMixing,
2893 : ErrorsFound,
2894 : zoneListNotAllowed);
2895 120 : state.dataHeatBal->TotCrossMixing = totZoneCrossMixing + state.dataHeatBal->airBoundaryMixing.size();
2896 :
2897 120 : if (state.dataHeatBal->TotCrossMixing > 0) {
2898 2 : cCurrentModuleObject = "ZoneCrossMixing";
2899 2 : state.dataHeatBal->CrossMixing.allocate(state.dataHeatBal->TotCrossMixing);
2900 :
2901 2 : int mixingNum = 0;
2902 11 : for (int mixingInputNum = 1; mixingInputNum <= numZoneCrossMixingInputObjects; ++mixingInputNum) {
2903 :
2904 9 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2905 : cCurrentModuleObject,
2906 : mixingInputNum,
2907 : cAlphaArgs,
2908 : NumAlpha,
2909 : rNumericArgs,
2910 : NumNumber,
2911 : IOStat,
2912 : lNumericFieldBlanks,
2913 : lAlphaFieldBlanks,
2914 : cAlphaFieldNames,
2915 : cNumericFieldNames);
2916 :
2917 9 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
2918 :
2919 : // Create one Mixing instance for every space associated with this input object
2920 9 : auto const &thisMixingInput = zoneCrossMixingInputObjects(mixingInputNum);
2921 19 : for (int Item1 = 1; Item1 <= thisMixingInput.numOfSpaces; ++Item1) {
2922 10 : ++mixingNum;
2923 10 : auto &thisMixing = state.dataHeatBal->CrossMixing(mixingNum);
2924 10 : thisMixing.Name = thisMixingInput.names(Item1);
2925 10 : thisMixing.spaceIndex = thisMixingInput.spaceNums(Item1);
2926 10 : auto const &thisSpace = state.dataHeatBal->space(thisMixing.spaceIndex);
2927 10 : thisMixing.ZonePtr = thisSpace.zoneNum;
2928 10 : auto &thisZone = state.dataHeatBal->Zone(thisSpace.zoneNum);
2929 :
2930 10 : if (lAlphaFieldBlanks(3)) {
2931 5 : thisMixing.sched = Sched::GetScheduleAlwaysOn(state); // not an availability schedule, but defaults to constant-1.0
2932 5 : } else if ((thisMixing.sched = Sched::GetSchedule(state, cAlphaArgs(3))) == nullptr) {
2933 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
2934 0 : ErrorsFound = true;
2935 : }
2936 :
2937 : // Mixing equipment design level calculation method.
2938 10 : AirflowSpec flow = static_cast<AirflowSpec>(getEnumValue(airflowSpecNamesUC, cAlphaArgs(4))); // NOLINT(modernize-use-auto)
2939 10 : switch (flow) {
2940 5 : case AirflowSpec::FlowPerZone:
2941 5 : thisMixing.DesignLevel = rNumericArgs(1);
2942 5 : if (lNumericFieldBlanks(1)) {
2943 0 : ShowWarningError(state,
2944 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
2945 : RoutineName,
2946 : cCurrentModuleObject,
2947 0 : thisMixingInput.Name,
2948 : cAlphaFieldNames(4),
2949 : cNumericFieldNames(1)));
2950 : } else {
2951 5 : Real64 spaceFrac = 1.0;
2952 5 : if (!thisMixingInput.spaceListActive && (thisMixingInput.numOfSpaces > 1)) {
2953 0 : Real64 const zoneVolume = thisZone.Volume;
2954 0 : if (zoneVolume > 0.0) {
2955 0 : spaceFrac = thisSpace.Volume / zoneVolume;
2956 : } else {
2957 0 : ShowSevereError(state, format("{}Zone volume is zero when allocating Cross Mixing to Spaces.", RoutineName));
2958 0 : ShowContinueError(
2959 0 : state, format("Occurs for {}=\"{}\" in Zone=\"{}\".", cCurrentModuleObject, thisMixingInput.Name, thisZone.Name));
2960 0 : ErrorsFound = true;
2961 : }
2962 : }
2963 :
2964 5 : thisMixing.DesignLevel = rNumericArgs(1) * spaceFrac;
2965 : }
2966 5 : break;
2967 :
2968 5 : case AirflowSpec::FlowPerArea:
2969 5 : if (thisMixing.spaceIndex != 0) {
2970 5 : if (rNumericArgs(2) >= 0.0) {
2971 5 : thisMixing.DesignLevel = rNumericArgs(2) * thisSpace.FloorArea;
2972 5 : if (thisMixing.spaceIndex > 0) {
2973 5 : if (thisZone.FloorArea <= 0.0) {
2974 0 : ShowWarningError(state,
2975 0 : format("{}{}=\"{}\", {} specifies {}, but Space Floor Area = 0. 0 Cross Mixing will result.",
2976 : RoutineName,
2977 : cCurrentModuleObject,
2978 0 : thisMixingInput.Name,
2979 : cAlphaFieldNames(4),
2980 : cNumericFieldNames(2)));
2981 : }
2982 : }
2983 : } else {
2984 0 : ShowSevereError(state,
2985 0 : format("{}{}=\"{}\", invalid flow/area specification [<0.0]={:.3R}",
2986 : RoutineName,
2987 : cCurrentModuleObject,
2988 0 : thisMixingInput.Name,
2989 : rNumericArgs(2)));
2990 0 : ErrorsFound = true;
2991 : }
2992 : }
2993 5 : if (lNumericFieldBlanks(2)) {
2994 0 : ShowWarningError(state,
2995 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
2996 : RoutineName,
2997 : cCurrentModuleObject,
2998 0 : thisMixingInput.Name,
2999 : cAlphaFieldNames(4),
3000 : cNumericFieldNames(2)));
3001 : }
3002 5 : break;
3003 :
3004 0 : case AirflowSpec::FlowPerPerson:
3005 0 : if (thisMixing.spaceIndex != 0) {
3006 0 : if (rNumericArgs(3) >= 0.0) {
3007 0 : thisMixing.DesignLevel = rNumericArgs(3) * thisSpace.TotOccupants;
3008 0 : if (thisSpace.TotOccupants <= 0.0) {
3009 0 : ShowWarningError(state,
3010 0 : format("{}{}=\"{}\", {} specifies {}, but Space Total Occupants = 0. 0 Cross Mixing will result.",
3011 : RoutineName,
3012 : cCurrentModuleObject,
3013 0 : thisMixingInput.Name,
3014 : cAlphaFieldNames(4),
3015 : cNumericFieldNames(3)));
3016 : }
3017 : } else {
3018 0 : ShowSevereError(state,
3019 0 : format("{}{}=\"{}\", invalid flow/person specification [<0.0]={:.3R}",
3020 : RoutineName,
3021 : cCurrentModuleObject,
3022 0 : thisMixingInput.Name,
3023 : rNumericArgs(3)));
3024 0 : ErrorsFound = true;
3025 : }
3026 : }
3027 0 : if (lNumericFieldBlanks(3)) {
3028 0 : ShowWarningError(state,
3029 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
3030 : RoutineName,
3031 : cCurrentModuleObject,
3032 0 : thisMixingInput.Name,
3033 : cAlphaFieldNames(4),
3034 : cNumericFieldNames(3)));
3035 : }
3036 0 : break;
3037 :
3038 0 : case AirflowSpec::AirChanges:
3039 0 : if (thisMixing.spaceIndex != 0) {
3040 0 : if (rNumericArgs(4) >= 0.0) {
3041 0 : thisMixing.DesignLevel = rNumericArgs(4) * thisSpace.Volume / Constant::rSecsInHour;
3042 0 : if (thisSpace.Volume <= 0.0) {
3043 0 : ShowWarningError(state,
3044 0 : format("{}{}=\"{}\", {} specifies {}, but Space Volume = 0. 0 Cross Mixing will result.",
3045 : RoutineName,
3046 : cCurrentModuleObject,
3047 0 : thisMixingInput.Name,
3048 : cAlphaFieldNames(4),
3049 : cNumericFieldNames(4)));
3050 : }
3051 : } else {
3052 0 : ShowSevereError(state,
3053 0 : format("{}{}=\"{}\", invalid ACH (air changes per hour) specification [<0.0]={:.3R}",
3054 : RoutineName,
3055 : cCurrentModuleObject,
3056 0 : thisMixingInput.Name,
3057 : rNumericArgs(4)));
3058 0 : ErrorsFound = true;
3059 : }
3060 : }
3061 0 : if (lNumericFieldBlanks(4)) {
3062 0 : ShowWarningError(state,
3063 0 : format("{}{}=\"{}\", {} specifies {}, but that field is blank. 0 Cross Mixing will result.",
3064 : RoutineName,
3065 : cCurrentModuleObject,
3066 0 : thisMixingInput.Name,
3067 : cAlphaFieldNames(4),
3068 : cNumericFieldNames(4)));
3069 : }
3070 0 : break;
3071 :
3072 0 : default:
3073 0 : ShowSevereError(
3074 0 : state, format("{}{}=\"{}\", invalid calculation method={}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), cAlphaArgs(4)));
3075 0 : ErrorsFound = true;
3076 : }
3077 :
3078 10 : thisMixing.fromSpaceIndex = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->space);
3079 10 : if (thisMixing.fromSpaceIndex == 0) {
3080 1 : thisMixing.FromZone = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
3081 : } else {
3082 9 : thisMixing.FromZone = state.dataHeatBal->space(thisMixing.fromSpaceIndex).zoneNum;
3083 : }
3084 10 : if ((thisMixing.FromZone == 0) && (thisMixing.fromSpaceIndex == 0)) {
3085 0 : ShowSevereError(state,
3086 0 : format("{}{}=\"{}\", invalid (not found) {}=\"{}\".",
3087 : RoutineName,
3088 : cCurrentModuleObject,
3089 : cAlphaArgs(1),
3090 : cAlphaFieldNames(5),
3091 : cAlphaArgs(5)));
3092 0 : ErrorsFound = true;
3093 : }
3094 10 : thisMixing.DeltaTemperature = rNumericArgs(5);
3095 :
3096 10 : if (NumAlpha > 5) {
3097 5 : if (lAlphaFieldBlanks(6)) {
3098 5 : if (lNumericFieldBlanks(5)) {
3099 0 : ShowWarningCustom(state,
3100 : eoh,
3101 0 : format("{} and {} are empty, a default temperature of {:.1R}C will be used.",
3102 : cAlphaFieldNames(6),
3103 : cNumericFieldNames(5),
3104 0 : thisMixing.DeltaTemperature));
3105 : }
3106 0 : } else if ((thisMixing.deltaTempSched = Sched::GetSchedule(state, cAlphaArgs(6))) == nullptr) {
3107 0 : ShowWarningItemNotFound(state,
3108 : eoh,
3109 0 : cAlphaFieldNames(6),
3110 0 : cAlphaArgs(6),
3111 0 : format("Fixed delta temperature {:.1R}C will be used", thisMixing.DeltaTemperature));
3112 0 : } else if (!thisMixing.deltaTempSched->checkMinVal(state, Clusive::In, 0.0)) {
3113 0 : Sched::ShowSevereBadMin(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6), Clusive::In, 0.0);
3114 0 : ErrorsFound = true;
3115 0 : } else if (!lNumericFieldBlanks(5)) {
3116 0 : ShowWarningCustom(
3117 : state,
3118 : eoh,
3119 0 : format("{} and {} provided. {} will be used.", cAlphaFieldNames(6), cNumericFieldNames(5), cAlphaFieldNames(6)));
3120 : }
3121 : }
3122 :
3123 : // Min indoor temp
3124 10 : if (NumAlpha > 6) {
3125 5 : if (lAlphaFieldBlanks(7)) {
3126 5 : } else if ((thisMixing.minIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(7))) == nullptr) {
3127 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(7), cAlphaArgs(7));
3128 0 : ErrorsFound = true;
3129 5 : } else if (!thisMixing.minIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3130 0 : Sched::ShowSevereBadMinMax(
3131 0 : state, eoh, cAlphaFieldNames(7), cAlphaArgs(7), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3132 0 : ErrorsFound = true;
3133 : }
3134 : }
3135 :
3136 : // Max indoor temp
3137 10 : if (NumAlpha > 7) {
3138 5 : if (lAlphaFieldBlanks(8)) {
3139 5 : } else if ((thisMixing.maxIndoorTempSched = Sched::GetSchedule(state, cAlphaArgs(8))) == nullptr) {
3140 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8));
3141 0 : ErrorsFound = true;
3142 5 : } else if (!thisMixing.maxIndoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3143 0 : Sched::ShowSevereBadMinMax(
3144 0 : state, eoh, cAlphaFieldNames(8), cAlphaArgs(8), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3145 0 : ErrorsFound = true;
3146 : }
3147 : }
3148 :
3149 : // Min source temp
3150 10 : if (NumAlpha > 8) {
3151 5 : if (lAlphaFieldBlanks(9)) {
3152 5 : } else if ((thisMixing.minSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(9))) == nullptr) {
3153 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(9), cAlphaArgs(9));
3154 0 : ErrorsFound = true;
3155 5 : } else if (!thisMixing.minSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3156 0 : Sched::ShowSevereBadMinMax(
3157 0 : state, eoh, cAlphaFieldNames(9), cAlphaArgs(9), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3158 0 : ErrorsFound = true;
3159 : }
3160 : }
3161 :
3162 : // Max source temp
3163 10 : if (NumAlpha > 9) {
3164 5 : if (lAlphaFieldBlanks(10)) {
3165 5 : } else if ((thisMixing.maxSourceTempSched = Sched::GetSchedule(state, cAlphaArgs(10))) == nullptr) {
3166 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(10), cAlphaArgs(10));
3167 0 : ErrorsFound = true;
3168 5 : } else if (!thisMixing.maxSourceTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3169 0 : Sched::ShowSevereBadMinMax(
3170 0 : state, eoh, cAlphaFieldNames(10), cAlphaArgs(10), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3171 0 : ErrorsFound = true;
3172 : }
3173 : }
3174 :
3175 : // Min outdoor temp
3176 10 : if (NumAlpha > 10) {
3177 5 : if (lAlphaFieldBlanks(11)) {
3178 5 : } else if ((thisMixing.minOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(11))) == nullptr) {
3179 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(11), cAlphaArgs(11));
3180 0 : ErrorsFound = true;
3181 5 : } else if (!thisMixing.minOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3182 0 : Sched::ShowSevereBadMinMax(
3183 0 : state, eoh, cAlphaFieldNames(11), cAlphaArgs(11), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3184 0 : ErrorsFound = true;
3185 : }
3186 : }
3187 :
3188 10 : if (NumAlpha > 11) {
3189 5 : if (lAlphaFieldBlanks(12)) {
3190 5 : } else if ((thisMixing.maxOutdoorTempSched = Sched::GetSchedule(state, cAlphaArgs(12))) == nullptr) {
3191 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(12), cAlphaArgs(12));
3192 0 : ErrorsFound = true;
3193 5 : } else if (!thisMixing.maxOutdoorTempSched->checkMinMaxVals(state, Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit)) {
3194 0 : Sched::ShowSevereBadMinMax(
3195 0 : state, eoh, cAlphaFieldNames(12), cAlphaArgs(12), Clusive::In, -MixingTempLimit, Clusive::In, MixingTempLimit);
3196 0 : ErrorsFound = true;
3197 : }
3198 : }
3199 : }
3200 : } // for (mixingInputNum)
3201 :
3202 : // Create CrossMixing objects from air boundary info
3203 2 : for (auto const &thisAirBoundaryMixing : state.dataHeatBal->airBoundaryMixing) {
3204 0 : ++mixingNum;
3205 : // Create CrossMixing object from air boundary info
3206 0 : int space1 = thisAirBoundaryMixing.space1;
3207 0 : int space2 = thisAirBoundaryMixing.space2;
3208 0 : int zone1 = state.dataHeatBal->space(space1).zoneNum;
3209 0 : int zone2 = state.dataHeatBal->space(space2).zoneNum;
3210 0 : auto &thisCrossMizing = state.dataHeatBal->CrossMixing(mixingNum);
3211 0 : thisCrossMizing.Name = fmt::format("Air Boundary Mixing Zones {} and {}", zone1, zone2);
3212 0 : thisCrossMizing.spaceIndex = space1;
3213 0 : thisCrossMizing.ZonePtr = zone1;
3214 0 : thisCrossMizing.sched = thisAirBoundaryMixing.sched;
3215 0 : thisCrossMizing.DesignLevel = thisAirBoundaryMixing.mixingVolumeFlowRate;
3216 0 : thisCrossMizing.FromZone = zone2;
3217 0 : thisCrossMizing.fromSpaceIndex = space2;
3218 2 : }
3219 2 : assert(mixingNum == state.dataHeatBal->TotCrossMixing);
3220 12 : for (int mixingRepNum = 1; mixingRepNum <= state.dataHeatBal->TotCrossMixing; ++mixingRepNum) {
3221 10 : int zoneNum = state.dataHeatBal->CrossMixing(mixingRepNum).ZonePtr;
3222 10 : if (zoneNum > 0) {
3223 10 : std::string const &zoneName = state.dataHeatBal->Zone(zoneNum).Name;
3224 10 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(zoneNum);
3225 10 : if (RepVarSet(zoneNum)) {
3226 3 : RepVarSet(zoneNum) = false;
3227 6 : SetupOutputVariable(state,
3228 : "Zone Mixing Volume",
3229 : Constant::Units::m3,
3230 3 : thisZnAirRpt.MixVolume,
3231 : OutputProcessor::TimeStepType::System,
3232 : OutputProcessor::StoreType::Sum,
3233 : zoneName);
3234 6 : SetupOutputVariable(state,
3235 : "Zone Mixing Current Density Volume Flow Rate",
3236 : Constant::Units::m3_s,
3237 3 : thisZnAirRpt.MixVdotCurDensity,
3238 : OutputProcessor::TimeStepType::System,
3239 : OutputProcessor::StoreType::Average,
3240 : zoneName);
3241 6 : SetupOutputVariable(state,
3242 : "Zone Mixing Standard Density Volume Flow Rate",
3243 : Constant::Units::m3_s,
3244 3 : thisZnAirRpt.MixVdotStdDensity,
3245 : OutputProcessor::TimeStepType::System,
3246 : OutputProcessor::StoreType::Average,
3247 : zoneName);
3248 6 : SetupOutputVariable(state,
3249 : "Zone Mixing Mass",
3250 : Constant::Units::kg,
3251 3 : thisZnAirRpt.MixMass,
3252 : OutputProcessor::TimeStepType::System,
3253 : OutputProcessor::StoreType::Sum,
3254 : zoneName);
3255 6 : SetupOutputVariable(state,
3256 : "Zone Mixing Mass Flow Rate",
3257 : Constant::Units::kg_s,
3258 3 : thisZnAirRpt.MixMdot,
3259 : OutputProcessor::TimeStepType::System,
3260 : OutputProcessor::StoreType::Average,
3261 : zoneName);
3262 6 : SetupOutputVariable(state,
3263 : "Zone Mixing Sensible Heat Loss Energy",
3264 : Constant::Units::J,
3265 3 : thisZnAirRpt.MixHeatLoss,
3266 : OutputProcessor::TimeStepType::System,
3267 : OutputProcessor::StoreType::Sum,
3268 : zoneName);
3269 6 : SetupOutputVariable(state,
3270 : "Zone Mixing Sensible Heat Gain Energy",
3271 : Constant::Units::J,
3272 3 : thisZnAirRpt.MixHeatGain,
3273 : OutputProcessor::TimeStepType::System,
3274 : OutputProcessor::StoreType::Sum,
3275 : zoneName);
3276 6 : SetupOutputVariable(state,
3277 : "Zone Mixing Latent Heat Loss Energy",
3278 : Constant::Units::J,
3279 3 : thisZnAirRpt.MixLatentLoss,
3280 : OutputProcessor::TimeStepType::System,
3281 : OutputProcessor::StoreType::Sum,
3282 : zoneName);
3283 6 : SetupOutputVariable(state,
3284 : "Zone Mixing Latent Heat Gain Energy",
3285 : Constant::Units::J,
3286 3 : thisZnAirRpt.MixLatentGain,
3287 : OutputProcessor::TimeStepType::System,
3288 : OutputProcessor::StoreType::Sum,
3289 : zoneName);
3290 6 : SetupOutputVariable(state,
3291 : "Zone Mixing Total Heat Loss Energy",
3292 : Constant::Units::J,
3293 3 : thisZnAirRpt.MixTotalLoss,
3294 : OutputProcessor::TimeStepType::System,
3295 : OutputProcessor::StoreType::Sum,
3296 : zoneName);
3297 6 : SetupOutputVariable(state,
3298 : "Zone Mixing Total Heat Gain Energy",
3299 : Constant::Units::J,
3300 3 : thisZnAirRpt.MixTotalGain,
3301 : OutputProcessor::TimeStepType::System,
3302 : OutputProcessor::StoreType::Sum,
3303 : zoneName);
3304 : }
3305 : }
3306 10 : int fromZoneNum = state.dataHeatBal->CrossMixing(mixingRepNum).FromZone;
3307 10 : if (fromZoneNum > 0) {
3308 10 : if (RepVarSet(fromZoneNum)) {
3309 1 : RepVarSet(fromZoneNum) = false;
3310 1 : std::string const &fromZoneName = state.dataHeatBal->Zone(fromZoneNum).Name;
3311 1 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(fromZoneNum);
3312 2 : SetupOutputVariable(state,
3313 : "Zone Mixing Volume",
3314 : Constant::Units::m3,
3315 1 : thisZnAirRpt.MixVolume,
3316 : OutputProcessor::TimeStepType::System,
3317 : OutputProcessor::StoreType::Sum,
3318 : fromZoneName);
3319 2 : SetupOutputVariable(state,
3320 : "Zone Mixing Current Density Volume Flow Rate",
3321 : Constant::Units::m3_s,
3322 1 : thisZnAirRpt.MixVdotCurDensity,
3323 : OutputProcessor::TimeStepType::System,
3324 : OutputProcessor::StoreType::Average,
3325 : fromZoneName);
3326 2 : SetupOutputVariable(state,
3327 : "Zone Mixing Standard Density Volume Flow Rate",
3328 : Constant::Units::m3_s,
3329 1 : thisZnAirRpt.MixVdotStdDensity,
3330 : OutputProcessor::TimeStepType::System,
3331 : OutputProcessor::StoreType::Average,
3332 : fromZoneName);
3333 2 : SetupOutputVariable(state,
3334 : "Zone Mixing Mass",
3335 : Constant::Units::kg,
3336 1 : thisZnAirRpt.MixMass,
3337 : OutputProcessor::TimeStepType::System,
3338 : OutputProcessor::StoreType::Sum,
3339 : fromZoneName);
3340 2 : SetupOutputVariable(state,
3341 : "Zone Mixing Mass Flow Rate",
3342 : Constant::Units::kg_s,
3343 1 : thisZnAirRpt.MixMdot,
3344 : OutputProcessor::TimeStepType::System,
3345 : OutputProcessor::StoreType::Average,
3346 : fromZoneName);
3347 2 : SetupOutputVariable(state,
3348 : "Zone Mixing Sensible Heat Loss Energy",
3349 : Constant::Units::J,
3350 1 : thisZnAirRpt.MixHeatLoss,
3351 : OutputProcessor::TimeStepType::System,
3352 : OutputProcessor::StoreType::Sum,
3353 : fromZoneName);
3354 2 : SetupOutputVariable(state,
3355 : "Zone Mixing Sensible Heat Gain Energy",
3356 : Constant::Units::J,
3357 1 : thisZnAirRpt.MixHeatGain,
3358 : OutputProcessor::TimeStepType::System,
3359 : OutputProcessor::StoreType::Sum,
3360 : fromZoneName);
3361 2 : SetupOutputVariable(state,
3362 : "Zone Mixing Latent Heat Loss Energy",
3363 : Constant::Units::J,
3364 1 : thisZnAirRpt.MixLatentLoss,
3365 : OutputProcessor::TimeStepType::System,
3366 : OutputProcessor::StoreType::Sum,
3367 : fromZoneName);
3368 2 : SetupOutputVariable(state,
3369 : "Zone Mixing Latent Heat Gain Energy",
3370 : Constant::Units::J,
3371 1 : thisZnAirRpt.MixLatentGain,
3372 : OutputProcessor::TimeStepType::System,
3373 : OutputProcessor::StoreType::Sum,
3374 : fromZoneName);
3375 2 : SetupOutputVariable(state,
3376 : "Zone Mixing Total Heat Loss Energy",
3377 : Constant::Units::J,
3378 1 : thisZnAirRpt.MixTotalLoss,
3379 : OutputProcessor::TimeStepType::System,
3380 : OutputProcessor::StoreType::Sum,
3381 : fromZoneName);
3382 2 : SetupOutputVariable(state,
3383 : "Zone Mixing Total Heat Gain Energy",
3384 : Constant::Units::J,
3385 1 : thisZnAirRpt.MixTotalGain,
3386 : OutputProcessor::TimeStepType::System,
3387 : OutputProcessor::StoreType::Sum,
3388 : fromZoneName);
3389 : }
3390 : }
3391 :
3392 10 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
3393 0 : SetupEMSActuator(state,
3394 : "ZoneCrossMixing",
3395 0 : state.dataHeatBal->CrossMixing(mixingRepNum).Name,
3396 : "Air Exchange Flow Rate",
3397 : "[m3/s]",
3398 0 : state.dataHeatBal->CrossMixing(mixingRepNum).EMSSimpleMixingOn,
3399 0 : state.dataHeatBal->CrossMixing(mixingRepNum).EMSimpleMixingFlowRate);
3400 : }
3401 : }
3402 : }
3403 :
3404 120 : cCurrentModuleObject = "ZoneRefrigerationDoorMixing";
3405 120 : state.dataHeatBal->TotRefDoorMixing = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
3406 120 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
3407 0 : state.dataHeatBal->RefDoorMixing.allocate(state.dataGlobal->NumOfZones);
3408 0 : for (auto &e : state.dataHeatBal->RefDoorMixing) {
3409 0 : e.NumRefDoorConnections = 0;
3410 0 : }
3411 :
3412 0 : for (int Loop = 1; Loop <= state.dataHeatBal->TotRefDoorMixing; ++Loop) {
3413 :
3414 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3415 : cCurrentModuleObject,
3416 : Loop,
3417 : cAlphaArgs,
3418 : NumAlpha,
3419 : rNumericArgs,
3420 : NumNumber,
3421 : IOStat,
3422 : lNumericFieldBlanks,
3423 : lAlphaFieldBlanks,
3424 : cAlphaFieldNames,
3425 : cNumericFieldNames);
3426 :
3427 0 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
3428 0 : NameThisObject = cAlphaArgs(1);
3429 :
3430 0 : int AlphaNum = 2;
3431 0 : int Zone1Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->Zone);
3432 0 : int space1Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->space);
3433 0 : if ((Zone1Num == 0) && (space1Num == 0)) {
3434 0 : ShowSevereError(state,
3435 0 : format("{}{}=\"{}\", invalid (not found) {}=\"{}\".",
3436 : RoutineName,
3437 : cCurrentModuleObject,
3438 : cAlphaArgs(1),
3439 : cAlphaFieldNames(AlphaNum),
3440 : cAlphaArgs(AlphaNum)));
3441 0 : ErrorsFound = true;
3442 0 : } else if (Zone1Num == 0) {
3443 0 : Zone1Num = state.dataHeatBal->space(space1Num).zoneNum;
3444 : }
3445 :
3446 0 : ++AlphaNum; // 3
3447 0 : int Zone2Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->Zone);
3448 0 : int space2Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->space);
3449 0 : if ((Zone2Num == 0) && (space2Num == 0)) {
3450 0 : ShowSevereError(state,
3451 0 : format("{}{}=\"{}\", invalid (not found) {}=\"{}\".",
3452 : RoutineName,
3453 : cCurrentModuleObject,
3454 : cAlphaArgs(1),
3455 : cAlphaFieldNames(AlphaNum),
3456 : cAlphaArgs(AlphaNum)));
3457 0 : ErrorsFound = true;
3458 0 : } else if (Zone2Num == 0) {
3459 0 : Zone2Num = state.dataHeatBal->space(space2Num).zoneNum;
3460 : }
3461 :
3462 0 : int spaceNumA = 0;
3463 0 : int spaceNumB = 0;
3464 0 : if (Zone1Num == Zone2Num) {
3465 0 : ShowSevereError(state,
3466 0 : format("{}{}=\"{}\", The same zone name has been entered for both sides of a refrigerated door {}=\"{}\".",
3467 : RoutineName,
3468 : cCurrentModuleObject,
3469 : cAlphaArgs(1),
3470 : cAlphaFieldNames(AlphaNum),
3471 : cAlphaArgs(AlphaNum)));
3472 0 : ErrorsFound = true;
3473 0 : } else if (Zone1Num < Zone2Num) { // zone 1 will come first in soln loop, id zone 2 as mate zone
3474 0 : ZoneNumA = Zone1Num;
3475 0 : ZoneNumB = Zone2Num;
3476 0 : spaceNumA = space1Num;
3477 0 : spaceNumB = space2Num;
3478 : } else { // zone 2 will come first in soln loop, id zone 1 as mate zone
3479 0 : ZoneNumA = Zone2Num;
3480 0 : ZoneNumB = Zone1Num;
3481 0 : spaceNumA = space2Num;
3482 0 : spaceNumB = space1Num;
3483 : }
3484 :
3485 0 : auto &zoneA = state.dataHeatBal->RefDoorMixing(ZoneNumA);
3486 0 : auto &zoneB = state.dataHeatBal->RefDoorMixing(ZoneNumB);
3487 :
3488 0 : if (!allocated(zoneA.openScheds)) {
3489 0 : zoneA.DoorMixingObjectName.allocate(state.dataGlobal->NumOfZones);
3490 0 : zoneA.openScheds.allocate(state.dataGlobal->NumOfZones);
3491 0 : zoneA.DoorHeight.allocate(state.dataGlobal->NumOfZones);
3492 0 : zoneA.DoorArea.allocate(state.dataGlobal->NumOfZones);
3493 0 : zoneA.Protection.allocate(state.dataGlobal->NumOfZones);
3494 0 : zoneA.MateZonePtr.allocate(state.dataGlobal->NumOfZones);
3495 0 : zoneA.EMSRefDoorMixingOn.allocate(state.dataGlobal->NumOfZones);
3496 0 : zoneA.EMSRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3497 0 : zoneA.VolRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3498 0 : zoneA.DoorProtTypeName.allocate(state.dataGlobal->NumOfZones);
3499 0 : zoneA.DoorMixingObjectName = "";
3500 0 : zoneA.openScheds = nullptr;
3501 0 : zoneA.DoorHeight = 0.0;
3502 0 : zoneA.DoorArea = 0.0;
3503 0 : zoneA.Protection = RefDoorNone;
3504 0 : zoneA.MateZonePtr = 0;
3505 0 : zoneA.EMSRefDoorMixingOn = false;
3506 0 : zoneA.EMSRefDoorFlowRate = 0.0;
3507 0 : zoneA.VolRefDoorFlowRate = 0.0;
3508 0 : zoneA.DoorProtTypeName = "";
3509 : } // First refrigeration mixing in this zone
3510 :
3511 0 : if (!allocated(zoneB.openScheds)) {
3512 0 : zoneB.DoorMixingObjectName.allocate(state.dataGlobal->NumOfZones);
3513 0 : zoneB.openScheds.allocate(state.dataGlobal->NumOfZones);
3514 0 : zoneB.DoorHeight.allocate(state.dataGlobal->NumOfZones);
3515 0 : zoneB.DoorArea.allocate(state.dataGlobal->NumOfZones);
3516 0 : zoneB.Protection.allocate(state.dataGlobal->NumOfZones);
3517 0 : zoneB.MateZonePtr.allocate(state.dataGlobal->NumOfZones);
3518 0 : zoneB.EMSRefDoorMixingOn.allocate(state.dataGlobal->NumOfZones);
3519 0 : zoneB.EMSRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3520 0 : zoneB.VolRefDoorFlowRate.allocate(state.dataGlobal->NumOfZones);
3521 0 : zoneB.DoorProtTypeName.allocate(state.dataGlobal->NumOfZones);
3522 0 : zoneB.DoorMixingObjectName = "";
3523 0 : zoneB.openScheds = nullptr;
3524 0 : zoneB.DoorHeight = 0.0;
3525 0 : zoneB.DoorArea = 0.0;
3526 0 : zoneB.Protection = RefDoorNone;
3527 0 : zoneB.MateZonePtr = 0;
3528 0 : zoneB.EMSRefDoorMixingOn = false;
3529 0 : zoneB.EMSRefDoorFlowRate = 0.0;
3530 0 : zoneB.VolRefDoorFlowRate = 0.0;
3531 0 : zoneB.DoorProtTypeName = "";
3532 : } // First refrigeration mixing in this zone
3533 :
3534 0 : ConnectionNumber = zoneA.NumRefDoorConnections + 1;
3535 0 : zoneA.NumRefDoorConnections = ConnectionNumber;
3536 0 : zoneA.ZonePtr = ZoneNumA;
3537 0 : zoneA.spaceIndex = spaceNumA;
3538 0 : zoneA.fromSpaceIndex = spaceNumB;
3539 0 : zoneA.MateZonePtr(ConnectionNumber) = ZoneNumB;
3540 0 : zoneA.DoorMixingObjectName(ConnectionNumber) = NameThisObject;
3541 : // need to make sure same pair of zones is only entered once.
3542 0 : if (zoneA.RefDoorMixFlag && zoneB.RefDoorMixFlag) {
3543 0 : if (zoneA.NumRefDoorConnections > 1) {
3544 0 : for (int ConnectTest = 1; ConnectTest <= (ConnectionNumber - 1); ++ConnectTest) {
3545 0 : if (zoneA.MateZonePtr(ConnectTest) != zoneA.MateZonePtr(ConnectionNumber)) {
3546 0 : continue;
3547 : }
3548 0 : ShowSevereError(
3549 : state,
3550 0 : format("{}{}=\"{}\", and {}", RoutineName, cCurrentModuleObject, cAlphaArgs(1), zoneA.DoorMixingObjectName(ConnectTest)));
3551 0 : ShowContinueError(state,
3552 0 : format(" Share same pair of zones: \"{}\" and \"{}\". Only one RefrigerationDoorMixing object is allowed "
3553 : "for any unique pair of zones.",
3554 0 : state.dataHeatBal->Zone(ZoneNumA).Name,
3555 0 : state.dataHeatBal->Zone(ZoneNumB).Name));
3556 0 : ErrorsFound = true;
3557 : } // ConnectTest
3558 : } // NumRefDoorconnections > 1
3559 0 : } else { // Both zones need to be flagged with ref doors
3560 0 : zoneA.RefDoorMixFlag = true;
3561 0 : zoneB.RefDoorMixFlag = true;
3562 : } // Both zones already flagged with ref doors
3563 :
3564 0 : ++AlphaNum; // 4
3565 0 : if (lAlphaFieldBlanks(AlphaNum)) {
3566 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(AlphaNum));
3567 0 : ErrorsFound = true;
3568 0 : } else if ((zoneA.openScheds(ConnectionNumber) = Sched::GetSchedule(state, cAlphaArgs(AlphaNum))) == nullptr) {
3569 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(AlphaNum), cAlphaArgs(AlphaNum));
3570 0 : ErrorsFound = true;
3571 0 : } else if (!zoneA.openScheds(ConnectionNumber)->checkMinMaxVals(state, Clusive::In, 0.0, Clusive::In, 1.0)) {
3572 0 : Sched::ShowSevereBadMinMax(state, eoh, cAlphaFieldNames(AlphaNum), cAlphaArgs(AlphaNum), Clusive::In, 0.0, Clusive::In, 1.0);
3573 0 : ErrorsFound = true;
3574 : } //(lAlphaFieldBlanks(AlphaNum)) THEN
3575 :
3576 0 : int NumbNum = 1;
3577 0 : if (lAlphaFieldBlanks(NumbNum)) {
3578 0 : zoneA.DoorHeight(ConnectionNumber) = 3.0; // default height of 3 meters
3579 0 : ShowWarningError(state,
3580 0 : format("{}{}=\"{}{} is blank and the default value of 3.0 will be used.",
3581 : RoutineName,
3582 : cCurrentModuleObject,
3583 : cAlphaArgs(1),
3584 : cNumericFieldNames(NumbNum)));
3585 : } else {
3586 0 : zoneA.DoorHeight(ConnectionNumber) = rNumericArgs(NumbNum);
3587 0 : if ((zoneA.DoorHeight(ConnectionNumber) < 0) || (zoneA.DoorHeight(ConnectionNumber) > 50.0)) {
3588 0 : ShowSevereError(
3589 : state,
3590 0 : format("{}{} = {} must have a door height between 0 and 50 meters. ", RoutineName, cCurrentModuleObject, cAlphaArgs(1)));
3591 0 : ErrorsFound = true;
3592 : }
3593 : }
3594 :
3595 0 : ++NumbNum; // 2
3596 0 : if (lAlphaFieldBlanks(NumbNum)) {
3597 0 : zoneA.DoorArea(ConnectionNumber) = 9.0; // default area of 9 m2
3598 0 : ShowWarningError(state,
3599 0 : format("{}{}=\"{}{} is blank and the default value of 9 m2 will be used.",
3600 : RoutineName,
3601 : cCurrentModuleObject,
3602 : cAlphaArgs(1),
3603 : cNumericFieldNames(NumbNum)));
3604 : } else {
3605 0 : zoneA.DoorArea(ConnectionNumber) = rNumericArgs(NumbNum);
3606 0 : if ((zoneA.DoorArea(ConnectionNumber) < 0) || (zoneA.DoorArea(ConnectionNumber) > 400.0)) {
3607 0 : ShowSevereError(
3608 : state,
3609 0 : format(
3610 : "{}{} = {} must have a door height between 0 and 400 square meters. ", RoutineName, cCurrentModuleObject, cAlphaArgs(1)));
3611 0 : ErrorsFound = true;
3612 : }
3613 : }
3614 :
3615 0 : ++AlphaNum; // 5
3616 : // Door protection type.
3617 0 : if (lAlphaFieldBlanks(AlphaNum)) {
3618 0 : zoneA.Protection(ConnectionNumber) = RefDoorNone; // Default
3619 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "None"; // Default
3620 0 : ShowWarningError(state,
3621 0 : format("{}{}=\"{}\" {} is blank. Default of no door protection will be used",
3622 : RoutineName,
3623 : cCurrentModuleObject,
3624 : cAlphaArgs(1),
3625 : cAlphaFieldNames(AlphaNum)));
3626 : } else {
3627 0 : if (cAlphaArgs(AlphaNum) == "NONE") {
3628 0 : zoneA.Protection(ConnectionNumber) = RefDoorNone;
3629 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "None";
3630 0 : } else if (cAlphaArgs(AlphaNum) == "AIRCURTAIN") {
3631 0 : zoneA.Protection(ConnectionNumber) = RefDoorAirCurtain;
3632 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "AirCurtain";
3633 0 : } else if (cAlphaArgs(AlphaNum) == "STRIPCURTAIN") {
3634 0 : zoneA.Protection(ConnectionNumber) = RefDoorStripCurtain;
3635 0 : zoneA.DoorProtTypeName(ConnectionNumber) = "StripCurtain";
3636 : } else {
3637 0 : ShowSevereError(state,
3638 0 : format("{}{}=\"{}\", invalid calculation method={} with alphanum of 5: {}",
3639 : RoutineName,
3640 : cCurrentModuleObject,
3641 : cAlphaArgs(1),
3642 : cAlphaArgs(AlphaNum),
3643 : cAlphaArgs(5)));
3644 0 : ErrorsFound = true;
3645 : } // =none, etc.
3646 : } // Blank
3647 :
3648 0 : if (ZoneNumA > 0) {
3649 0 : if (RepVarSet(ZoneNumA)) {
3650 0 : RepVarSet(ZoneNumA) = false;
3651 0 : SetupOutputVariable(state,
3652 : "Zone Mixing Volume",
3653 : Constant::Units::m3,
3654 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixVolume,
3655 : OutputProcessor::TimeStepType::System,
3656 : OutputProcessor::StoreType::Sum,
3657 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3658 0 : SetupOutputVariable(state,
3659 : "Zone Mixing Current Density Volume Flow Rate",
3660 : Constant::Units::m3_s,
3661 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixVdotCurDensity,
3662 : OutputProcessor::TimeStepType::System,
3663 : OutputProcessor::StoreType::Average,
3664 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3665 0 : SetupOutputVariable(state,
3666 : "Zone Mixing Standard Density Volume Flow Rate",
3667 : Constant::Units::m3_s,
3668 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixVdotStdDensity,
3669 : OutputProcessor::TimeStepType::System,
3670 : OutputProcessor::StoreType::Average,
3671 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3672 0 : SetupOutputVariable(state,
3673 : "Zone Mixing Mass",
3674 : Constant::Units::kg,
3675 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixMass,
3676 : OutputProcessor::TimeStepType::System,
3677 : OutputProcessor::StoreType::Sum,
3678 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3679 0 : SetupOutputVariable(state,
3680 : "Zone Mixing Mass Flow Rate",
3681 : Constant::Units::kg_s,
3682 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixMdot,
3683 : OutputProcessor::TimeStepType::System,
3684 : OutputProcessor::StoreType::Average,
3685 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3686 0 : SetupOutputVariable(state,
3687 : "Zone Mixing Sensible Heat Loss Energy",
3688 : Constant::Units::J,
3689 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixHeatLoss,
3690 : OutputProcessor::TimeStepType::System,
3691 : OutputProcessor::StoreType::Sum,
3692 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3693 0 : SetupOutputVariable(state,
3694 : "Zone Mixing Sensible Heat Gain Energy",
3695 : Constant::Units::J,
3696 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixHeatGain,
3697 : OutputProcessor::TimeStepType::System,
3698 : OutputProcessor::StoreType::Sum,
3699 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3700 0 : SetupOutputVariable(state,
3701 : "Zone Mixing Latent Heat Loss Energy",
3702 : Constant::Units::J,
3703 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixLatentLoss,
3704 : OutputProcessor::TimeStepType::System,
3705 : OutputProcessor::StoreType::Sum,
3706 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3707 0 : SetupOutputVariable(state,
3708 : "Zone Mixing Latent Heat Gain Energy",
3709 : Constant::Units::J,
3710 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixLatentGain,
3711 : OutputProcessor::TimeStepType::System,
3712 : OutputProcessor::StoreType::Sum,
3713 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3714 0 : SetupOutputVariable(state,
3715 : "Zone Mixing Total Heat Loss Energy",
3716 : Constant::Units::J,
3717 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixTotalLoss,
3718 : OutputProcessor::TimeStepType::System,
3719 : OutputProcessor::StoreType::Sum,
3720 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3721 0 : SetupOutputVariable(state,
3722 : "Zone Mixing Total Heat Gain Energy",
3723 : Constant::Units::J,
3724 0 : state.dataHeatBal->ZnAirRpt(ZoneNumA).MixTotalGain,
3725 : OutputProcessor::TimeStepType::System,
3726 : OutputProcessor::StoreType::Sum,
3727 0 : state.dataHeatBal->Zone(ZoneNumA).Name);
3728 : }
3729 : }
3730 0 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
3731 0 : SetupEMSActuator(state,
3732 : "ZoneRefDoorMixing",
3733 : zoneA.Name,
3734 : "Air Exchange Flow Rate",
3735 : "[m3/s]",
3736 : zoneA.EMSRefDoorMixingOn(ConnectionNumber),
3737 0 : zoneA.EMSRefDoorFlowRate(ConnectionNumber));
3738 : }
3739 :
3740 0 : if (ZoneNumB > 0) {
3741 0 : if (RepVarSet(ZoneNumB)) {
3742 0 : RepVarSet(ZoneNumB) = false;
3743 0 : SetupOutputVariable(state,
3744 : "Zone Mixing Volume",
3745 : Constant::Units::m3,
3746 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixVolume,
3747 : OutputProcessor::TimeStepType::System,
3748 : OutputProcessor::StoreType::Sum,
3749 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3750 0 : SetupOutputVariable(state,
3751 : "Zone Mixing Current Density Volume Flow Rate",
3752 : Constant::Units::m3_s,
3753 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixVdotCurDensity,
3754 : OutputProcessor::TimeStepType::System,
3755 : OutputProcessor::StoreType::Average,
3756 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3757 0 : SetupOutputVariable(state,
3758 : "Zone Mixing Standard Density Volume Flow Rate",
3759 : Constant::Units::m3_s,
3760 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixVdotStdDensity,
3761 : OutputProcessor::TimeStepType::System,
3762 : OutputProcessor::StoreType::Average,
3763 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3764 0 : SetupOutputVariable(state,
3765 : "Zone Mixing Mass",
3766 : Constant::Units::kg,
3767 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixMass,
3768 : OutputProcessor::TimeStepType::System,
3769 : OutputProcessor::StoreType::Sum,
3770 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3771 0 : SetupOutputVariable(state,
3772 : "Zone Mixing Mass Flow Rate",
3773 : Constant::Units::kg_s,
3774 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixMdot,
3775 : OutputProcessor::TimeStepType::System,
3776 : OutputProcessor::StoreType::Average,
3777 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3778 0 : SetupOutputVariable(state,
3779 : "Zone Mixing Sensible Heat Loss Energy",
3780 : Constant::Units::J,
3781 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixHeatLoss,
3782 : OutputProcessor::TimeStepType::System,
3783 : OutputProcessor::StoreType::Sum,
3784 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3785 0 : SetupOutputVariable(state,
3786 : "Zone Mixing Sensible Heat Gain Energy",
3787 : Constant::Units::J,
3788 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixHeatGain,
3789 : OutputProcessor::TimeStepType::System,
3790 : OutputProcessor::StoreType::Sum,
3791 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3792 0 : SetupOutputVariable(state,
3793 : "Zone Mixing Latent Heat Loss Energy",
3794 : Constant::Units::J,
3795 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixLatentLoss,
3796 : OutputProcessor::TimeStepType::System,
3797 : OutputProcessor::StoreType::Sum,
3798 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3799 0 : SetupOutputVariable(state,
3800 : "Zone Mixing Latent Heat Gain Energy",
3801 : Constant::Units::J,
3802 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixLatentGain,
3803 : OutputProcessor::TimeStepType::System,
3804 : OutputProcessor::StoreType::Sum,
3805 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3806 0 : SetupOutputVariable(state,
3807 : "Zone Mixing Total Heat Loss Energy",
3808 : Constant::Units::J,
3809 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixTotalLoss,
3810 : OutputProcessor::TimeStepType::System,
3811 : OutputProcessor::StoreType::Sum,
3812 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3813 0 : SetupOutputVariable(state,
3814 : "Zone Mixing Total Heat Gain Energy",
3815 : Constant::Units::J,
3816 0 : state.dataHeatBal->ZnAirRpt(ZoneNumB).MixTotalGain,
3817 : OutputProcessor::TimeStepType::System,
3818 : OutputProcessor::StoreType::Sum,
3819 0 : state.dataHeatBal->Zone(ZoneNumB).Name);
3820 : }
3821 : }
3822 0 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
3823 0 : SetupEMSActuator(state,
3824 : "ZoneRefDoorMixing",
3825 : zoneB.Name,
3826 : "Air Exchange Flow Rate",
3827 : "[m3/s]",
3828 : zoneA.EMSRefDoorMixingOn(ConnectionNumber),
3829 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).EMSRefDoorFlowRate(ConnectionNumber));
3830 : }
3831 : } // DO Loop=1,TotRefDoorMixing
3832 : } // TotRefDoorMixing > 0)
3833 :
3834 120 : RepVarSet.deallocate();
3835 120 : cAlphaArgs.deallocate();
3836 120 : cAlphaFieldNames.deallocate();
3837 120 : cNumericFieldNames.deallocate();
3838 120 : rNumericArgs.deallocate();
3839 120 : lAlphaFieldBlanks.deallocate();
3840 120 : lNumericFieldBlanks.deallocate();
3841 :
3842 120 : TotInfilVentFlow.dimension(state.dataGlobal->NumOfZones, 0.0);
3843 :
3844 255 : auto divide_and_print_if_greater_than_zero = [&](const Real64 denominator, const Real64 numerator) {
3845 255 : if (denominator > 0.0) {
3846 143 : print(state.files.eio, "{:.3R},", numerator / denominator);
3847 : } else {
3848 112 : print(state.files.eio, "N/A,");
3849 : }
3850 255 : };
3851 :
3852 171 : for (int Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
3853 51 : if (Loop == 1) {
3854 21 : print(state.files.eio,
3855 : Format_721,
3856 : "ZoneInfiltration",
3857 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/Exterior Surface Area {m3/s-m2},ACH - "
3858 : "Air Changes per Hour,Equation A - Constant Term Coefficient {},Equation B - Temperature Term Coefficient {1/C},Equation C - "
3859 : "Velocity Term Coefficient {s/m}, Equation D - Velocity Squared Term Coefficient {s2/m2}");
3860 : }
3861 :
3862 51 : int ZoneNum = state.dataHeatBal->Infiltration(Loop).ZonePtr;
3863 51 : if (ZoneNum == 0) {
3864 0 : print(state.files.eio, Format_722, "Infiltration-Illegal Zone specified", state.dataHeatBal->Infiltration(Loop).Name);
3865 0 : continue;
3866 : }
3867 51 : TotInfilVentFlow(ZoneNum) += state.dataHeatBal->Infiltration(Loop).DesignLevel;
3868 51 : print(state.files.eio,
3869 : Format_720,
3870 : "ZoneInfiltration",
3871 51 : state.dataHeatBal->Infiltration(Loop).Name,
3872 51 : state.dataHeatBal->Infiltration(Loop).sched->Name,
3873 51 : state.dataHeatBal->Zone(ZoneNum).Name,
3874 51 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
3875 51 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
3876 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).DesignLevel);
3877 :
3878 51 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->Infiltration(Loop).DesignLevel);
3879 51 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).ExteriorTotalSurfArea,
3880 51 : state.dataHeatBal->Infiltration(Loop).DesignLevel);
3881 51 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
3882 51 : state.dataHeatBal->Infiltration(Loop).DesignLevel * Constant::rSecsInHour);
3883 :
3884 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).ConstantTermCoef);
3885 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).TemperatureTermCoef);
3886 51 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Infiltration(Loop).VelocityTermCoef);
3887 51 : print(state.files.eio, "{:.3R}\n", state.dataHeatBal->Infiltration(Loop).VelocitySQTermCoef);
3888 : }
3889 :
3890 120 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
3891 19 : for (int Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
3892 11 : int ZoneNum = state.dataHeatBal->Infiltration(Loop).ZonePtr;
3893 11 : state.dataHeatBal->MassConservation(ZoneNum).InfiltrationPtr = Loop;
3894 : }
3895 : }
3896 :
3897 130 : for (int Loop = 1; Loop <= state.dataHeatBal->TotVentilation; ++Loop) {
3898 10 : if (Loop == 1) {
3899 1 : print(state.files.eio,
3900 : Format_721,
3901 : "ZoneVentilation",
3902 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/person Area {m3/s-person},ACH - Air "
3903 : "Changes per Hour,Fan Type {Exhaust;Intake;Natural},Fan Pressure Rise {Pa},Fan Efficiency {},Equation A - Constant Term "
3904 : "Coefficient {},Equation B - Temperature Term Coefficient {1/C},Equation C - Velocity Term Coefficient {s/m}, Equation D - "
3905 : "Velocity Squared Term Coefficient {s2/m2},Minimum Indoor Temperature{C}/Schedule,Maximum Indoor "
3906 : "Temperature{C}/Schedule,Delta Temperature{C}/Schedule,Minimum Outdoor Temperature{C}/Schedule,Maximum Outdoor "
3907 : "Temperature{C}/Schedule,Maximum WindSpeed{m/s}");
3908 : }
3909 :
3910 10 : int ZoneNum = state.dataHeatBal->Ventilation(Loop).ZonePtr;
3911 10 : if (ZoneNum == 0) {
3912 0 : print(state.files.eio, Format_722, "Ventilation-Illegal Zone specified", state.dataHeatBal->Ventilation(Loop).Name);
3913 0 : continue;
3914 : }
3915 10 : TotInfilVentFlow(ZoneNum) += state.dataHeatBal->Ventilation(Loop).DesignLevel;
3916 10 : print(state.files.eio,
3917 : Format_720,
3918 : "ZoneVentilation",
3919 10 : state.dataHeatBal->Ventilation(Loop).Name,
3920 10 : state.dataHeatBal->Ventilation(Loop).availSched->Name,
3921 10 : state.dataHeatBal->Zone(ZoneNum).Name,
3922 10 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
3923 10 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
3924 :
3925 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).DesignLevel);
3926 :
3927 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->Ventilation(Loop).DesignLevel);
3928 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).TotOccupants, state.dataHeatBal->Ventilation(Loop).DesignLevel);
3929 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
3930 10 : state.dataHeatBal->Ventilation(Loop).DesignLevel * Constant::rSecsInHour);
3931 :
3932 10 : if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Exhaust) {
3933 0 : print(state.files.eio, "Exhaust,");
3934 10 : } else if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Intake) {
3935 0 : print(state.files.eio, "Intake,");
3936 10 : } else if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Natural) {
3937 10 : print(state.files.eio, "Natural,");
3938 0 : } else if (state.dataHeatBal->Ventilation(Loop).FanType == DataHeatBalance::VentilationType::Balanced) {
3939 0 : print(state.files.eio, "Balanced,");
3940 : } else {
3941 0 : print(state.files.eio, "UNKNOWN,");
3942 : }
3943 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).FanPressure);
3944 10 : print(state.files.eio, "{:.1R},", state.dataHeatBal->Ventilation(Loop).FanEfficiency);
3945 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).ConstantTermCoef);
3946 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).TemperatureTermCoef);
3947 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).VelocityTermCoef);
3948 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Ventilation(Loop).VelocitySQTermCoef);
3949 :
3950 : // TODO Should this also be prefixed with "Schedule: " like the following ones are?
3951 10 : if (state.dataHeatBal->Ventilation(Loop).minIndoorTempSched != nullptr) {
3952 0 : print(state.files.eio, "{},", state.dataHeatBal->Ventilation(Loop).minIndoorTempSched->Name);
3953 : } else {
3954 10 : print(state.files.eio, "{:.2R},", state.dataHeatBal->Ventilation(Loop).MinIndoorTemperature);
3955 : }
3956 :
3957 40 : const auto print_temperature = [&](Sched::Schedule const *ptr, const Real64 value) {
3958 40 : if (ptr != nullptr) {
3959 0 : print(state.files.eio, "Schedule: {},", ptr->Name);
3960 : } else {
3961 40 : print(state.files.eio, "{:.2R},", value);
3962 : }
3963 40 : };
3964 :
3965 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).maxIndoorTempSched, state.dataHeatBal->Ventilation(Loop).MaxIndoorTemperature);
3966 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).deltaTempSched, state.dataHeatBal->Ventilation(Loop).DelTemperature);
3967 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).minOutdoorTempSched, state.dataHeatBal->Ventilation(Loop).MinOutdoorTemperature);
3968 10 : print_temperature(state.dataHeatBal->Ventilation(Loop).maxOutdoorTempSched, state.dataHeatBal->Ventilation(Loop).MaxOutdoorTemperature);
3969 :
3970 10 : print(state.files.eio, "{:.2R}\n", state.dataHeatBal->Ventilation(Loop).MaxWindSpeed);
3971 : }
3972 :
3973 120 : TotMixingFlow.dimension(state.dataGlobal->NumOfZones, 0.0);
3974 134 : for (int Loop = 1; Loop <= state.dataHeatBal->TotMixing; ++Loop) {
3975 14 : if (Loop == 1) {
3976 8 : print(state.files.eio,
3977 : Format_721,
3978 : "Mixing",
3979 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/person Area {m3/s-person},ACH - Air "
3980 : "Changes per Hour,From/Source Zone,Delta Temperature {C}");
3981 : }
3982 :
3983 14 : int ZoneNum = state.dataHeatBal->Mixing(Loop).ZonePtr;
3984 14 : if (ZoneNum == 0) {
3985 0 : print(state.files.eio, Format_722, "Mixing-Illegal Zone specified", state.dataHeatBal->Mixing(Loop).Name);
3986 0 : continue;
3987 : }
3988 14 : TotMixingFlow(ZoneNum) += state.dataHeatBal->Mixing(Loop).DesignLevel;
3989 14 : print(state.files.eio,
3990 : Format_720,
3991 : "Mixing",
3992 14 : state.dataHeatBal->Mixing(Loop).Name,
3993 14 : state.dataHeatBal->Mixing(Loop).sched->Name,
3994 14 : state.dataHeatBal->Zone(ZoneNum).Name,
3995 14 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
3996 14 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
3997 14 : print(state.files.eio, "{:.3R},", state.dataHeatBal->Mixing(Loop).DesignLevel);
3998 14 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->Mixing(Loop).DesignLevel);
3999 14 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).TotOccupants, state.dataHeatBal->Mixing(Loop).DesignLevel);
4000 14 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
4001 14 : state.dataHeatBal->Mixing(Loop).DesignLevel * Constant::rSecsInHour);
4002 :
4003 14 : print(state.files.eio, "{},", state.dataHeatBal->Zone(state.dataHeatBal->Mixing(Loop).FromZone).Name);
4004 14 : print(state.files.eio, "{:.2R}\n", state.dataHeatBal->Mixing(Loop).DeltaTemperature);
4005 : }
4006 :
4007 130 : for (int Loop = 1; Loop <= state.dataHeatBal->TotCrossMixing; ++Loop) {
4008 10 : if (Loop == 1) {
4009 2 : print(state.files.eio,
4010 : Format_721,
4011 : "CrossMixing",
4012 : "Design Volume Flow Rate {m3/s},Volume Flow Rate/Floor Area {m3/s-m2},Volume Flow Rate/person Area {m3/s-person},ACH - Air "
4013 : "Changes per Hour,From/Source Zone,Delta Temperature {C}");
4014 : }
4015 :
4016 10 : int ZoneNum = state.dataHeatBal->CrossMixing(Loop).ZonePtr;
4017 10 : if (ZoneNum == 0) {
4018 0 : print(state.files.eio, Format_722, "CrossMixing-Illegal Zone specified", state.dataHeatBal->CrossMixing(Loop).Name);
4019 0 : continue;
4020 : }
4021 10 : TotMixingFlow(ZoneNum) += state.dataHeatBal->CrossMixing(Loop).DesignLevel;
4022 10 : print(state.files.eio,
4023 : Format_720,
4024 : "CrossMixing",
4025 10 : state.dataHeatBal->CrossMixing(Loop).Name,
4026 10 : state.dataHeatBal->CrossMixing(Loop).sched->Name,
4027 10 : state.dataHeatBal->Zone(ZoneNum).Name,
4028 10 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
4029 10 : state.dataHeatBal->Zone(ZoneNum).TotOccupants);
4030 :
4031 10 : print(state.files.eio, "{:.3R},", state.dataHeatBal->CrossMixing(Loop).DesignLevel);
4032 :
4033 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).FloorArea, state.dataHeatBal->CrossMixing(Loop).DesignLevel);
4034 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).TotOccupants, state.dataHeatBal->CrossMixing(Loop).DesignLevel);
4035 10 : divide_and_print_if_greater_than_zero(state.dataHeatBal->Zone(ZoneNum).Volume,
4036 10 : state.dataHeatBal->CrossMixing(Loop).DesignLevel * Constant::rSecsInHour);
4037 :
4038 10 : print(state.files.eio, "{},", state.dataHeatBal->Zone(state.dataHeatBal->CrossMixing(Loop).FromZone).Name);
4039 10 : print(state.files.eio, "{:.2R}\n", state.dataHeatBal->CrossMixing(Loop).DeltaTemperature);
4040 : }
4041 :
4042 120 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
4043 : static constexpr std::string_view Format_724("! <{} Airflow Stats Nominal>, {}\n");
4044 0 : print(state.files.eio,
4045 : Format_724,
4046 : "RefrigerationDoorMixing ",
4047 : "Name, Zone 1 Name,Zone 2 Name,Door Opening Schedule Name,Door Height {m},Door Area {m2},Door Protection Type");
4048 0 : for (ZoneNumA = 1; ZoneNumA <= (state.dataGlobal->NumOfZones - 1); ++ZoneNumA) {
4049 0 : if (!state.dataHeatBal->RefDoorMixing(ZoneNumA).RefDoorMixFlag) {
4050 0 : continue;
4051 : }
4052 0 : for (ConnectionNumber = 1; ConnectionNumber <= state.dataHeatBal->RefDoorMixing(ZoneNumA).NumRefDoorConnections; ++ConnectionNumber) {
4053 0 : ZoneNumB = state.dataHeatBal->RefDoorMixing(ZoneNumA).MateZonePtr(ConnectionNumber);
4054 : // TotMixingFlow(ZoneNum)=TotMixingFlow(ZoneNum)+RefDoorMixing(Loop)%!DesignLevel
4055 : static constexpr std::string_view Format_723(" {} Airflow Stats Nominal, {},{},{},{},{:.3R},{:.3R},{}\n");
4056 0 : print(state.files.eio,
4057 : Format_723,
4058 : "RefrigerationDoorMixing",
4059 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorMixingObjectName(ConnectionNumber),
4060 0 : state.dataHeatBal->Zone(ZoneNumA).Name,
4061 0 : state.dataHeatBal->Zone(ZoneNumB).Name,
4062 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).openScheds(ConnectionNumber)->Name,
4063 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorHeight(ConnectionNumber),
4064 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorArea(ConnectionNumber),
4065 0 : state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorProtTypeName(ConnectionNumber));
4066 : } // ConnectionNumber
4067 : } // ZoneNumA
4068 : } //(TotRefDoorMixing .GT. 0)
4069 :
4070 283 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4071 163 : state.dataHeatBal->Zone(ZoneNum).NominalInfilVent = TotInfilVentFlow(ZoneNum);
4072 163 : state.dataHeatBal->Zone(ZoneNum).NominalMixing = TotMixingFlow(ZoneNum);
4073 : }
4074 :
4075 120 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
4076 : // Check for infiltration in zone which are only a mixing source zone
4077 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4078 18 : if ((state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing &&
4079 24 : state.dataHeatBal->MassConservation(ZoneNum).IsOnlySourceZone) &&
4080 6 : (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment != DataHeatBalance::InfiltrationFlow::No)) {
4081 5 : if (state.dataHeatBal->MassConservation(ZoneNum).InfiltrationPtr == 0) {
4082 0 : ShowSevereError(
4083 0 : state, format("{}: Infiltration object is not defined for zone = {}", RoutineName, state.dataHeatBal->Zone(ZoneNum).Name));
4084 0 : ShowContinueError(state, "Zone air mass flow balance requires infiltration object for source zones of mixing objects");
4085 : }
4086 : }
4087 : }
4088 : // Set up zone air mass balance output variables
4089 26 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4090 36 : SetupOutputVariable(state,
4091 : "Zone Air Mass Balance Supply Mass Flow Rate",
4092 : Constant::Units::kg_s,
4093 18 : state.dataHeatBal->MassConservation(ZoneNum).InMassFlowRate,
4094 : OutputProcessor::TimeStepType::System,
4095 : OutputProcessor::StoreType::Average,
4096 18 : state.dataHeatBal->Zone(ZoneNum).Name);
4097 36 : SetupOutputVariable(state,
4098 : "Zone Air Mass Balance Exhaust Mass Flow Rate",
4099 : Constant::Units::kg_s,
4100 18 : state.dataHeatBal->MassConservation(ZoneNum).ExhMassFlowRate,
4101 : OutputProcessor::TimeStepType::System,
4102 : OutputProcessor::StoreType::Average,
4103 18 : state.dataHeatBal->Zone(ZoneNum).Name);
4104 36 : SetupOutputVariable(state,
4105 : "Zone Air Mass Balance Return Mass Flow Rate",
4106 : Constant::Units::kg_s,
4107 18 : state.dataHeatBal->MassConservation(ZoneNum).RetMassFlowRate,
4108 : OutputProcessor::TimeStepType::System,
4109 : OutputProcessor::StoreType::Average,
4110 18 : state.dataHeatBal->Zone(ZoneNum).Name);
4111 34 : if ((state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) &&
4112 16 : ((state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject +
4113 16 : state.dataHeatBal->MassConservation(ZoneNum).NumReceivingZonesMixingObject) > 0)) {
4114 28 : SetupOutputVariable(state,
4115 : "Zone Air Mass Balance Mixing Receiving Mass Flow Rate",
4116 : Constant::Units::kg_s,
4117 14 : state.dataHeatBal->MassConservation(ZoneNum).MixingMassFlowRate,
4118 : OutputProcessor::TimeStepType::System,
4119 : OutputProcessor::StoreType::Average,
4120 14 : state.dataHeatBal->Zone(ZoneNum).Name);
4121 28 : SetupOutputVariable(state,
4122 : "Zone Air Mass Balance Mixing Source Mass Flow Rate",
4123 : Constant::Units::kg_s,
4124 14 : state.dataHeatBal->MassConservation(ZoneNum).MixingSourceMassFlowRate,
4125 : OutputProcessor::TimeStepType::System,
4126 : OutputProcessor::StoreType::Average,
4127 14 : state.dataHeatBal->Zone(ZoneNum).Name);
4128 : }
4129 18 : if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationTreatment != DataHeatBalance::InfiltrationFlow::No) {
4130 15 : if (state.dataHeatBal->ZoneAirMassFlow.InfiltrationForZones == DataHeatBalance::InfiltrationZoneType::AllZones ||
4131 0 : (state.dataHeatBal->MassConservation(ZoneNum).NumSourceZonesMixingObject > 0)) {
4132 15 : if (state.dataHeatBal->MassConservation(ZoneNum).InfiltrationPtr > 0) {
4133 22 : SetupOutputVariable(state,
4134 : "Zone Air Mass Balance Infiltration Mass Flow Rate",
4135 : Constant::Units::kg_s,
4136 11 : state.dataHeatBal->MassConservation(ZoneNum).InfiltrationMassFlowRate,
4137 : OutputProcessor::TimeStepType::System,
4138 : OutputProcessor::StoreType::Average,
4139 11 : state.dataHeatBal->Zone(ZoneNum).Name);
4140 11 : SetupOutputVariable(state,
4141 : "Zone Air Mass Balance Infiltration Status",
4142 : Constant::Units::None,
4143 11 : state.dataHeatBal->MassConservation(ZoneNum).IncludeInfilToZoneMassBal,
4144 : OutputProcessor::TimeStepType::System,
4145 : OutputProcessor::StoreType::Average,
4146 11 : state.dataHeatBal->Zone(ZoneNum).Name);
4147 : }
4148 : }
4149 : }
4150 : }
4151 : }
4152 :
4153 120 : TotInfilVentFlow.deallocate();
4154 120 : TotMixingFlow.deallocate();
4155 : // ' Area per Occupant {m2/person}, Occupant per Area {person/m2}, Interior Lighting {W/m2}, ', &
4156 : // 'Electric Load {W/m2}, Gas Load {W/m2}, Other Load {W/m2}, Hot Water Eq {W/m2}, Outdoor Controlled Baseboard Heat')
4157 120 : }
4158 :
4159 106 : void GetRoomAirModelParameters(EnergyPlusData &state, bool &errFlag) // True if errors found during this input routine
4160 : {
4161 :
4162 : // SUBROUTINE INFORMATION:
4163 : // AUTHOR Brent Griffith
4164 : // DATE WRITTEN August 2001
4165 : // RE-ENGINEERED April 2003, Weixiu Kong
4166 : // December 2003, CC
4167 :
4168 : // PURPOSE OF THIS SUBROUTINE:
4169 : // Get room air model parameters for all zones at once
4170 :
4171 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4172 : int NumAlphas; // States which alpha value to read from a
4173 : // "Number" line
4174 : int NumNumbers; // Number of numbers encountered
4175 : int Status; // Notes if there was an error in processing the input
4176 : int AirModelNum;
4177 : int NumOfAirModels;
4178 : int ZoneNum;
4179 : bool IsNotOK;
4180 :
4181 : // Initialize default values for air model parameters
4182 106 : state.dataRoomAir->AirModel.allocate(state.dataGlobal->NumOfZones);
4183 :
4184 106 : bool ErrorsFound = false;
4185 106 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
4186 :
4187 106 : cCurrentModuleObject = "RoomAirModelType";
4188 106 : NumOfAirModels = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
4189 106 : if (NumOfAirModels > state.dataGlobal->NumOfZones) {
4190 0 : ShowSevereError(state, format("Too many {}. Cannot exceed the number of Zones.", cCurrentModuleObject));
4191 0 : ErrorsFound = true;
4192 : }
4193 106 : if (NumOfAirModels > 0) {
4194 2 : state.dataRoomAir->IsZoneDispVent3Node.dimension(state.dataGlobal->NumOfZones, false);
4195 2 : state.dataRoomAir->IsZoneCrossVent.dimension(state.dataGlobal->NumOfZones, false);
4196 2 : state.dataRoomAir->IsZoneUFAD.dimension(state.dataGlobal->NumOfZones, false);
4197 : }
4198 :
4199 109 : for (AirModelNum = 1; AirModelNum <= NumOfAirModels; ++AirModelNum) {
4200 9 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
4201 : cCurrentModuleObject,
4202 : AirModelNum,
4203 3 : state.dataIPShortCut->cAlphaArgs,
4204 : NumAlphas,
4205 3 : state.dataIPShortCut->rNumericArgs,
4206 : NumNumbers,
4207 : Status,
4208 : _,
4209 : _,
4210 3 : state.dataIPShortCut->cAlphaFieldNames,
4211 3 : state.dataIPShortCut->cNumericFieldNames);
4212 3 : ZoneNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
4213 3 : if (ZoneNum != 0) {
4214 3 : if (!state.dataRoomAir->AirModel(ZoneNum).Name.empty()) {
4215 0 : ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
4216 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4217 0 : ShowContinueError(state, "Duplicate zone name, only one type of roomair model is allowed per zone");
4218 0 : ShowContinueError(state,
4219 0 : format("Zone {} was already assigned a roomair model by {} = {}",
4220 0 : state.dataIPShortCut->cAlphaArgs(2),
4221 : cCurrentModuleObject,
4222 0 : roomAirModelNamesUC[(int)state.dataRoomAir->AirModel(ZoneNum).AirModel]));
4223 0 : ShowContinueError(
4224 : state,
4225 0 : format("Air Model Type for zone already set to {}", roomAirModelNamesUC[(int)state.dataRoomAir->AirModel(ZoneNum).AirModel]));
4226 0 : ShowContinueError(state, format("Trying to overwrite with model type = {}", state.dataIPShortCut->cAlphaArgs(3)));
4227 0 : ErrorsFound = true;
4228 : }
4229 3 : state.dataRoomAir->AirModel(ZoneNum).ZoneName = state.dataIPShortCut->cAlphaArgs(2);
4230 :
4231 : // state.dataRoomAir->AirModel(ZoneNum).AirModelName = state.dataIPShortCut->cAlphaArgs(1);
4232 3 : state.dataRoomAir->AirModel(ZoneNum).AirModel =
4233 3 : static_cast<RoomAir::RoomAirModel>(getEnumValue(roomAirModelNamesUC, state.dataIPShortCut->cAlphaArgs(3))); // is this arg1 or arg3?
4234 3 : switch (state.dataRoomAir->AirModel(ZoneNum).AirModel) {
4235 0 : case RoomAir::RoomAirModel::Mixing:
4236 : // nothing to do here actually
4237 0 : break;
4238 :
4239 0 : case RoomAir::RoomAirModel::DispVent1Node:
4240 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4241 0 : state.dataRoomAir->DispVent1NodeModelUsed = true;
4242 0 : IsNotOK = false;
4243 0 : ValidateComponent(state,
4244 : "RoomAirSettings:OneNodeDisplacementVentilation",
4245 : "zone_name",
4246 0 : state.dataIPShortCut->cAlphaArgs(2),
4247 : IsNotOK,
4248 : "GetRoomAirModelParameters");
4249 0 : if (IsNotOK) {
4250 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4251 0 : ErrorsFound = true;
4252 : }
4253 0 : break;
4254 :
4255 0 : case RoomAir::RoomAirModel::DispVent3Node:
4256 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4257 0 : state.dataRoomAir->UCSDModelUsed = true;
4258 0 : IsNotOK = false;
4259 0 : ValidateComponent(state,
4260 : "RoomAirSettings:ThreeNodeDisplacementVentilation",
4261 : "zone_name",
4262 0 : state.dataIPShortCut->cAlphaArgs(2),
4263 : IsNotOK,
4264 : "GetRoomAirModelParameters");
4265 0 : if (IsNotOK) {
4266 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4267 0 : ErrorsFound = true;
4268 : }
4269 0 : break;
4270 :
4271 0 : case RoomAir::RoomAirModel::CrossVent:
4272 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4273 0 : state.dataRoomAir->UCSDModelUsed = true;
4274 0 : IsNotOK = false;
4275 0 : ValidateComponent(state,
4276 : "RoomAirSettings:CrossVentilation",
4277 : "zone_name",
4278 0 : state.dataIPShortCut->cAlphaArgs(2),
4279 : IsNotOK,
4280 : "GetRoomAirModelParameters");
4281 0 : if (IsNotOK) {
4282 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4283 0 : ErrorsFound = true;
4284 : }
4285 0 : break;
4286 :
4287 0 : case RoomAir::RoomAirModel::UFADInt:
4288 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4289 0 : state.dataRoomAir->UCSDModelUsed = true;
4290 0 : ValidateComponent(state,
4291 : "RoomAirSettings:UnderFloorAirDistributionInterior",
4292 : "zone_name",
4293 0 : state.dataIPShortCut->cAlphaArgs(2),
4294 : IsNotOK,
4295 : "GetRoomAirModelParameters");
4296 0 : if (IsNotOK) {
4297 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4298 0 : ErrorsFound = true;
4299 : }
4300 0 : break;
4301 :
4302 0 : case RoomAir::RoomAirModel::UFADExt:
4303 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4304 0 : state.dataRoomAir->UCSDModelUsed = true;
4305 0 : ValidateComponent(state,
4306 : "RoomAirSettings:UnderFloorAirDistributionExterior",
4307 : "zone_name",
4308 0 : state.dataIPShortCut->cAlphaArgs(2),
4309 : IsNotOK,
4310 : "GetRoomAirModelParameters");
4311 0 : if (IsNotOK) {
4312 0 : ShowContinueError(state, format("In {}={}.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4313 0 : ErrorsFound = true;
4314 : }
4315 0 : break;
4316 :
4317 0 : case RoomAir::RoomAirModel::UserDefined:
4318 0 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4319 0 : state.dataRoomAir->UserDefinedUsed = true;
4320 0 : break;
4321 :
4322 3 : case RoomAir::RoomAirModel::AirflowNetwork:
4323 3 : state.dataRoomAir->AirModel(ZoneNum).SimAirModel = true;
4324 3 : if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirflowNetwork:SimulationControl") == 0) {
4325 4 : ShowSevereError(state,
4326 6 : format("In {} = {}: {} = AIRFLOWNETWORK.",
4327 : cCurrentModuleObject,
4328 2 : state.dataIPShortCut->cAlphaArgs(1),
4329 2 : state.dataIPShortCut->cAlphaFieldNames(3)));
4330 4 : ShowContinueError(state,
4331 : "This model requires AirflowNetwork:* objects to form a complete network, including "
4332 : "AirflowNetwork:Intrazone:Node and AirflowNetwork:Intrazone:Linkage.");
4333 4 : ShowContinueError(state, "AirflowNetwork:SimulationControl not found.");
4334 2 : ErrorsFound = true;
4335 : }
4336 3 : break;
4337 :
4338 0 : default:
4339 0 : ShowWarningError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
4340 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4341 0 : ShowContinueError(state, format("The mixing air model will be used for Zone ={}", state.dataIPShortCut->cAlphaArgs(2)));
4342 0 : state.dataRoomAir->AirModel(ZoneNum).AirModel = RoomAir::RoomAirModel::Mixing;
4343 : }
4344 :
4345 3 : state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme =
4346 3 : static_cast<RoomAir::CouplingScheme>(getEnumValue(couplingSchemeNamesUC, state.dataIPShortCut->cAlphaArgs(4)));
4347 3 : if (state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme == RoomAir::CouplingScheme::Invalid) {
4348 0 : ShowWarningError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4)));
4349 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4350 0 : ShowContinueError(state, format("The direct coupling scheme will be used for Zone ={}", state.dataIPShortCut->cAlphaArgs(2)));
4351 0 : state.dataRoomAir->AirModel(ZoneNum).TempCoupleScheme = RoomAir::CouplingScheme::Direct;
4352 : }
4353 :
4354 : } else { // Zone Not Found
4355 0 : ShowSevereError(state, format("{}, Zone not found={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(2)));
4356 0 : ShowContinueError(state, format("occurs in {}={}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4357 0 : ErrorsFound = true;
4358 : }
4359 : } // AirModel_Param_Loop
4360 :
4361 242 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4362 : // this used to be an if (NumOfAirModels == 0) block, but both the IF and the ELSE had the same content, these two lines:
4363 136 : state.dataRoomAir->AirModel(ZoneNum).Name = "MIXING AIR MODEL FOR " + state.dataHeatBal->Zone(ZoneNum).Name;
4364 136 : state.dataRoomAir->AirModel(ZoneNum).ZoneName = state.dataHeatBal->Zone(ZoneNum).Name;
4365 : // set global flag for non-mixing model
4366 136 : if (state.dataRoomAir->AirModel(ZoneNum).AirModel != RoomAir::RoomAirModel::Mixing) {
4367 3 : state.dataRoomAir->anyNonMixingRoomAirModel = true;
4368 : }
4369 : }
4370 :
4371 106 : if (state.dataRoomAir->anyNonMixingRoomAirModel) {
4372 2 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
4373 0 : ShowSevereError(state, "Non-Mixing RoomAirModelType is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
4374 0 : ErrorsFound = true;
4375 : }
4376 : }
4377 :
4378 : // Write RoomAir Model details onto EIO file
4379 : static constexpr std::string_view RoomAirHeader("! <RoomAir Model>, Zone Name, Mixing/Mundt/UCSDDV/UCSDCV/UCSDUFI/UCSDUFE/User Defined\n");
4380 106 : print(state.files.eio, RoomAirHeader);
4381 242 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
4382 : static constexpr std::array<std::string_view, (int)RoomAir::RoomAirModel::Num> roomAirModelStrings = {"UserDefined",
4383 : "Mixing/Well-Stirred",
4384 : "OneNodeDisplacementVentilation",
4385 : "ThreeNodeDisplacementVentilation",
4386 : "CrossVentilation",
4387 : "UnderFloorAirDistributionInterior",
4388 : "UnderFloorAirDistributionExterior",
4389 : "AirflowNetwork"};
4390 :
4391 136 : print(state.files.eio,
4392 : "RoomAir Model,{},{}\n",
4393 136 : state.dataHeatBal->Zone(ZoneNum).Name,
4394 136 : roomAirModelStrings[(int)state.dataRoomAir->AirModel(ZoneNum).AirModel]);
4395 : }
4396 :
4397 106 : if (ErrorsFound) {
4398 1 : ShowSevereError(state, format("Errors found in processing input for {}", cCurrentModuleObject));
4399 1 : errFlag = true;
4400 : }
4401 106 : }
4402 :
4403 249951 : void InitAirHeatBalance(EnergyPlusData &state)
4404 : {
4405 :
4406 : // SUBROUTINE INFORMATION:
4407 : // AUTHOR Richard J. Liesen
4408 : // DATE WRITTEN February 1998
4409 :
4410 : // PURPOSE OF THIS SUBROUTINE:
4411 : // This subroutine is for initializations within the
4412 : // air heat balance.
4413 :
4414 : // Do the following initializations (every time step):
4415 249951 : InitSimpleMixingConvectiveHeatGains(state);
4416 249951 : }
4417 :
4418 249955 : void InitSimpleMixingConvectiveHeatGains(EnergyPlusData &state)
4419 : {
4420 : // SUBROUTINE INFORMATION:
4421 : // AUTHOR Richard Liesen
4422 : // DATE WRITTEN February 1998
4423 : // MODIFIED March 2003, FCW: allow individual window/door venting control
4424 : // DATE MODIFIED April 2000
4425 : // May 2009, Brent Griffith added EMS override to mixing and cross mixing flows
4426 : // renamed routine and did some cleanup
4427 : // August 2011, Therese Stovall added refrigeration door mixing flows
4428 :
4429 : // PURPOSE OF THIS SUBROUTINE:
4430 : // This subroutine sets up the mixing and cross mixing flows
4431 :
4432 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4433 : Real64 ZoneMixingFlowSum; // sum of zone mixing flows for a zone
4434 :
4435 : // Select type of airflow calculation
4436 249955 : if (state.dataHeatBal->AirFlowFlag) { // Simplified airflow calculation
4437 : // Process the scheduled Mixing for air heat balance
4438 255741 : for (auto &thisMixing : state.dataHeatBal->Mixing) {
4439 5787 : thisMixing.DesiredAirFlowRate = thisMixing.DesignLevel * thisMixing.sched->getCurrentVal();
4440 5787 : if (thisMixing.EMSSimpleMixingOn) {
4441 0 : thisMixing.DesiredAirFlowRate = thisMixing.EMSimpleMixingFlowRate;
4442 : }
4443 5787 : thisMixing.DesiredAirFlowRateSaved = thisMixing.DesiredAirFlowRate;
4444 249954 : }
4445 :
4446 : // if zone air mass flow balance enforced calculate the fraction of
4447 : // contribution of each mixing object to a zone mixed flow rate, BAN Feb 2014
4448 249954 : if (state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
4449 22 : for (auto &massConservZone : state.dataHeatBal->MassConservation) {
4450 15 : ZoneMixingFlowSum = 0.0;
4451 15 : int NumOfMixingObjects = massConservZone.NumReceivingZonesMixingObject;
4452 25 : for (int Loop = 1; Loop <= NumOfMixingObjects; ++Loop) {
4453 10 : ZoneMixingFlowSum += state.dataHeatBal->Mixing(Loop).DesignLevel;
4454 10 : massConservZone.ZoneMixingReceivingFr(Loop) = 0.0;
4455 : }
4456 15 : if (ZoneMixingFlowSum > 0.0) {
4457 15 : for (int Loop = 1; Loop <= NumOfMixingObjects; ++Loop) {
4458 8 : massConservZone.ZoneMixingReceivingFr(Loop) = state.dataHeatBal->Mixing(Loop).DesignLevel / ZoneMixingFlowSum;
4459 : }
4460 : }
4461 7 : }
4462 : }
4463 :
4464 : // Process the scheduled CrossMixing for air heat balance
4465 255734 : for (auto &thisCrossMix : state.dataHeatBal->CrossMixing) {
4466 5780 : thisCrossMix.DesiredAirFlowRate = thisCrossMix.DesignLevel * thisCrossMix.sched->getCurrentVal();
4467 5780 : if (thisCrossMix.EMSSimpleMixingOn) {
4468 0 : thisCrossMix.DesiredAirFlowRate = thisCrossMix.EMSimpleMixingFlowRate;
4469 : }
4470 249954 : }
4471 :
4472 : // Note - do each Pair a Single time, so must do increment reports for both zones
4473 : // Can't have a pair that has ZoneA zone number = NumOfZones because organized
4474 : // in input with lowest zone # first no matter how input in idf
4475 :
4476 : // Process the scheduled Refrigeration Door mixing for air heat balance
4477 249954 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
4478 0 : for (int NZ = 1; NZ <= (state.dataGlobal->NumOfZones - 1);
4479 : ++NZ) { // Can't have %ZonePtr==NumOfZones because lesser zone # of pair placed in ZonePtr in input
4480 0 : auto &thisRefDoor = state.dataHeatBal->RefDoorMixing(NZ);
4481 0 : if (!thisRefDoor.RefDoorMixFlag) {
4482 0 : continue;
4483 : }
4484 0 : if (thisRefDoor.ZonePtr == NZ) {
4485 0 : for (int J = 1; J <= thisRefDoor.NumRefDoorConnections; ++J) {
4486 0 : thisRefDoor.VolRefDoorFlowRate(J) = 0.0;
4487 0 : if (thisRefDoor.EMSRefDoorMixingOn(J)) {
4488 0 : thisRefDoor.VolRefDoorFlowRate(J) = thisRefDoor.EMSRefDoorFlowRate(J);
4489 : }
4490 : }
4491 : }
4492 : }
4493 : } // TotRefDoorMixing
4494 :
4495 : // Infiltration and ventilation calculations have been moved to a subroutine of CalcAirFlowSimple in HVAC Manager
4496 : }
4497 249955 : }
4498 :
4499 249946 : void CalcHeatBalanceAir(EnergyPlusData &state)
4500 : {
4501 :
4502 : // PURPOSE OF THIS SUBROUTINE:
4503 : // This subroutine calculates the air component of the heat balance.
4504 :
4505 249946 : if (state.dataGlobal->externalHVACManager) {
4506 1353 : if (!state.dataGlobal->externalHVACManagerInitialized) {
4507 1353 : initializeForExternalHVACManager(state);
4508 : }
4509 1353 : state.dataGlobal->externalHVACManager(&state);
4510 : } else {
4511 248593 : HVACManager::ManageHVAC(state);
4512 : }
4513 249945 : }
4514 :
4515 : // END Algorithm Section of the Module
4516 :
4517 1353 : void initializeForExternalHVACManager(EnergyPlusData &state)
4518 : {
4519 : // this function will ultimately provide a nice series of calls that initialize all the hvac stuff needed
4520 : // to allow an external hvac manager to play nice with E+
4521 1353 : EnergyPlus::ZoneTempPredictorCorrector::InitZoneAirSetPoints(state);
4522 1353 : }
4523 :
4524 249945 : void ReportZoneMeanAirTemp(EnergyPlusData &state)
4525 : {
4526 : // SUBROUTINE INFORMATION:
4527 : // AUTHOR Linda Lawrie
4528 : // DATE WRITTEN July 2000
4529 :
4530 : // PURPOSE OF THIS SUBROUTINE:
4531 : // This subroutine updates the report variables for the AirHeatBalance.
4532 249945 : if (state.dataHeatBalAirMgr->CalcExtraReportVarMyOneTimeFlag) {
4533 572 : for (auto const *reqVar : state.dataOutputProcessor->reqVars) {
4534 469 : if (reqVar->name == "ZONE WETBULB GLOBE TEMPERATURE") {
4535 21 : if (reqVar->key.empty()) {
4536 0 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
4537 0 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(ZoneLoop);
4538 0 : thisZnAirRpt.ReportWBGT = true;
4539 : }
4540 : } else {
4541 21 : int ZoneLoop = Util::FindItemInList(Util::makeUPPER(reqVar->key), state.dataHeatBal->Zone);
4542 21 : if (ZoneLoop > 0) {
4543 21 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(ZoneLoop);
4544 21 : thisZnAirRpt.ReportWBGT = true;
4545 : }
4546 : }
4547 448 : } else if (reqVar->name == "SPACE WETBULB GLOBE TEMPERATURE") {
4548 0 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
4549 0 : if (reqVar->key.empty()) {
4550 0 : for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
4551 0 : auto &thisSpaceAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
4552 0 : thisSpaceAirRpt.ReportWBGT = true;
4553 : }
4554 : } else {
4555 0 : int spaceNum = Util::FindItemInList(Util::makeUPPER(reqVar->key), 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 : }
4564 :
4565 : // EMS sensor request WBGT check
4566 108 : for (int loop = 1; loop <= state.dataRuntimeLang->NumSensors; ++loop) {
4567 5 : if (state.dataRuntimeLang->Sensor(loop).OutputVarName == "ZONE WETBULB GLOBE TEMPERATURE") {
4568 0 : int ZoneLoop = Util::FindItemInList(state.dataRuntimeLang->Sensor(loop).UniqueKeyName, state.dataHeatBal->Zone);
4569 0 : if (ZoneLoop > 0) {
4570 0 : auto &thisZnAirRpt = state.dataHeatBal->ZnAirRpt(ZoneLoop);
4571 0 : thisZnAirRpt.ReportWBGT = true;
4572 : }
4573 5 : } else if (state.dataRuntimeLang->Sensor(loop).OutputVarName == "SPACE WETBULB GLOBE TEMPERATURE") {
4574 0 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
4575 0 : int spaceNum = Util::FindItemInList(state.dataRuntimeLang->Sensor(loop).UniqueKeyName, state.dataHeatBal->space);
4576 0 : if (spaceNum > 0) {
4577 0 : auto &thisSpaceAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
4578 0 : thisSpaceAirRpt.ReportWBGT = true;
4579 : }
4580 : }
4581 : }
4582 : }
4583 103 : state.dataHeatBalAirMgr->CalcExtraReportVarMyOneTimeFlag = false;
4584 : }
4585 586584 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
4586 336639 : auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop);
4587 336639 : calcMeanAirTemps(state, thisZoneHB.ZTAV, thisZoneHB.airHumRatAvg, thisZoneHB.MRT, state.dataHeatBal->ZnAirRpt(ZoneLoop), ZoneLoop);
4588 336639 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation) {
4589 5775 : for (int spaceNum : state.dataHeatBal->Zone(ZoneLoop).spaceIndexes) {
4590 3465 : auto const &thisSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum);
4591 3465 : calcMeanAirTemps(
4592 6930 : state, thisSpaceHB.ZTAV, thisSpaceHB.airHumRatAvg, thisSpaceHB.MRT, state.dataHeatBal->spaceAirRpt(spaceNum), ZoneLoop);
4593 2310 : }
4594 : }
4595 : }
4596 249945 : }
4597 :
4598 340104 : void calcMeanAirTemps(EnergyPlusData &state,
4599 : Real64 const ZTAV,
4600 : Real64 const airHumRatAvg,
4601 : Real64 const MRT,
4602 : DataHeatBalance::AirReportVars &thisAirRpt,
4603 : int const zoneNum)
4604 : {
4605 : // The mean air temperature is actually ZTAV which is the average
4606 : // temperature of the air temperatures at the system time step for the
4607 : // entire zone time step.
4608 340104 : thisAirRpt.MeanAirTemp = ZTAV;
4609 340104 : thisAirRpt.MeanAirHumRat = airHumRatAvg;
4610 340104 : thisAirRpt.OperativeTemp = 0.5 * (ZTAV + MRT);
4611 340104 : thisAirRpt.MeanAirDewPointTemp = Psychrometrics::PsyTdpFnWPb(state, thisAirRpt.MeanAirHumRat, state.dataEnvrn->OutBaroPress);
4612 :
4613 : // if operative temperature control is being used, then radiative fraction/weighting
4614 : // might be defined by user to be something different than 0.5, even scheduled over simulation period
4615 340104 : if (state.dataZoneCtrls->AnyOpTempControl) { // dig further...
4616 : // find TempControlledZoneID from ZoneLoop index
4617 0 : int TempControlledZoneID = state.dataHeatBal->Zone(zoneNum).TempControlledZoneIndex;
4618 0 : if (state.dataHeatBal->Zone(zoneNum).IsControlled) {
4619 0 : if ((state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).OpTempCtrl != DataZoneControls::TempCtrl::None)) {
4620 : Real64 thisMRTFraction; // temp working value for radiative fraction/weight
4621 : // is operative temp radiative fraction scheduled or fixed?
4622 0 : if (state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).OpTempCtrl == DataZoneControls::TempCtrl::Scheduled) {
4623 0 : thisMRTFraction = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).opTempRadiativeFractionSched->getCurrentVal();
4624 : } else {
4625 0 : thisMRTFraction = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID).FixedRadiativeFraction;
4626 : }
4627 0 : thisAirRpt.OperativeTemp = 0.5 * (ZTAV + MRT);
4628 0 : thisAirRpt.ThermOperativeTemp = (1.0 - thisMRTFraction) * ZTAV + thisMRTFraction * MRT;
4629 : }
4630 : }
4631 : }
4632 340104 : if (thisAirRpt.ReportWBGT) {
4633 : // note that the WetBulbTemp here is for temporary verification, it will not be another added reporting variable
4634 72565 : thisAirRpt.WetbulbGlobeTemp =
4635 72565 : 0.7 * Psychrometrics::PsyTwbFnTdbWPb(state, ZTAV, airHumRatAvg, state.dataEnvrn->OutBaroPress) + 0.3 * thisAirRpt.OperativeTemp;
4636 : }
4637 340104 : }
4638 :
4639 : } // namespace EnergyPlus::HeatBalanceAirManager
|