Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cmath>
51 : #include <string>
52 :
53 : // ObjexxFCL Headers
54 : #include <ObjexxFCL/Array.functions.hh>
55 : #include <ObjexxFCL/Fmath.hh>
56 :
57 : // EnergyPlus Headers
58 : #include <AirflowNetwork/Solver.hpp>
59 : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
60 : #include <EnergyPlus/Data/EnergyPlusData.hh>
61 : #include <EnergyPlus/DataAirLoop.hh>
62 : #include <EnergyPlus/DataAirSystems.hh>
63 : #include <EnergyPlus/DataConvergParams.hh>
64 : #include <EnergyPlus/DataHVACGlobals.hh>
65 : #include <EnergyPlus/DataHeatBalFanSys.hh>
66 : #include <EnergyPlus/DataHeatBalance.hh>
67 : #include <EnergyPlus/DataLoopNode.hh>
68 : #include <EnergyPlus/DataReportingFlags.hh>
69 : #include <EnergyPlus/DataSurfaces.hh>
70 : #include <EnergyPlus/DataSystemVariables.hh>
71 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
72 : #include <EnergyPlus/DemandManager.hh>
73 : #include <EnergyPlus/DisplayRoutines.hh>
74 : #include <EnergyPlus/EMSManager.hh>
75 : #include <EnergyPlus/ElectricPowerServiceManager.hh>
76 : #include <EnergyPlus/Fans.hh>
77 : #include <EnergyPlus/General.hh>
78 : #include <EnergyPlus/HVACManager.hh>
79 : #include <EnergyPlus/HVACSizingSimulationManager.hh>
80 : #include <EnergyPlus/IceThermalStorage.hh>
81 : #include <EnergyPlus/InternalHeatGains.hh>
82 : #include <EnergyPlus/NodeInputManager.hh>
83 : #include <EnergyPlus/NonZoneEquipmentManager.hh>
84 : #include <EnergyPlus/OutAirNodeManager.hh>
85 : #include <EnergyPlus/OutputProcessor.hh>
86 : #include <EnergyPlus/OutputReportTabular.hh>
87 : #include <EnergyPlus/Plant/DataPlant.hh>
88 : #include <EnergyPlus/Plant/PlantManager.hh>
89 : #include <EnergyPlus/PlantCondLoopOperation.hh>
90 : #include <EnergyPlus/PlantLoopHeatPumpEIR.hh>
91 : #include <EnergyPlus/PlantUtilities.hh>
92 : #include <EnergyPlus/PollutionModule.hh>
93 : #include <EnergyPlus/Psychrometrics.hh>
94 : #include <EnergyPlus/RefrigeratedCase.hh>
95 : #include <EnergyPlus/ScheduleManager.hh>
96 : #include <EnergyPlus/SetPointManager.hh>
97 : #include <EnergyPlus/SimAirServingZones.hh>
98 : #include <EnergyPlus/SizingManager.hh>
99 : #include <EnergyPlus/SystemAvailabilityManager.hh>
100 : #include <EnergyPlus/SystemReports.hh>
101 : #include <EnergyPlus/UtilityRoutines.hh>
102 : #include <EnergyPlus/WaterManager.hh>
103 : #include <EnergyPlus/ZoneContaminantPredictorCorrector.hh>
104 : #include <EnergyPlus/ZoneEquipmentManager.hh>
105 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
106 :
107 : namespace EnergyPlus::HVACManager {
108 :
109 : // PURPOSE OF THIS MODULE:
110 : // This module contains the high level HVAC control
111 : // subroutines. Subroutine ManageHVAC, which is called from the heat balance,
112 : // calls the HVAC simulation and is the most probable insertion point for
113 : // connections to other HVAC engines. ManageHVAC also controls the system
114 : // timestep, automatically shortening the timestep to meet convergence criteria.
115 :
116 : // METHODOLOGY EMPLOYED:
117 : // The basic solution technique is iteration with lagging.
118 : // The timestep is shortened using a bisection method.
119 :
120 : using namespace DataEnvironment;
121 : using namespace DataHVACGlobals;
122 : using namespace DataLoopNode;
123 : using namespace DataAirLoop;
124 :
125 : static constexpr std::array<Real64, DataPlant::NumConvergenceHistoryTerms> ConvergenceHistoryARR = {0.0, -1.0, -2.0, -3.0, -4.0};
126 : constexpr Real64 sum_ConvergenceHistoryARR(-10.0);
127 : constexpr Real64 square_sum_ConvergenceHistoryARR(100.0);
128 : constexpr Real64 sum_square_ConvergenceHistoryARR(30.0);
129 :
130 2568313 : void ManageHVAC(EnergyPlusData &state)
131 : {
132 :
133 : // SUBROUTINE INFORMATION:
134 : // AUTHORS: Russ Taylor, Dan Fisher
135 : // DATE WRITTEN: Jan. 1998
136 : // MODIFIED Jul 2003 (CC) added a subroutine call for air models
137 : // RE-ENGINEERED May 2008, Brent Griffith, revised variable time step method and zone conditions history
138 :
139 : // PURPOSE OF THIS SUBROUTINE:
140 : // This routine effectively replaces the IBLAST
141 : // "SystemDriver" routine. The main function of the routine
142 : // is to set the system timestep, "TimeStepSys", call the models related to zone
143 : // air temperatures, and .
144 :
145 : // METHODOLOGY EMPLOYED:
146 : // manage calls to Predictor and Corrector and other updates in ZoneTempPredictorCorrector
147 : // manage variable time step and when zone air histories are updated.
148 :
149 : // Using/Aliasing
150 : using DemandManager::ManageDemand;
151 : using DemandManager::UpdateDemandManagers;
152 : using EMSManager::ManageEMS;
153 : using InternalHeatGains::UpdateInternalGainValues;
154 : using NodeInputManager::CalcMoreNodeInfo;
155 : using OutAirNodeManager::SetOutAirNodes;
156 : using OutputReportTabular::GatherComponentLoadsHVAC;
157 : using OutputReportTabular::UpdateTabularReports; // added for writing tabular output reports
158 : using PollutionModule::CalculatePollution;
159 : using RefrigeratedCase::ManageRefrigeratedCaseRacks;
160 : using ScheduleManager::GetCurrentScheduleValue;
161 : using SizingManager::UpdateFacilitySizing;
162 : using SystemAvailabilityManager::ManageHybridVentilation;
163 : using SystemReports::InitEnergyReports;
164 : using SystemReports::ReportSystemEnergyUse;
165 : using WaterManager::ManageWater;
166 : using WaterManager::ManageWaterInits;
167 : using ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates;
168 : using ZoneEquipmentManager::CalcAirFlowSimple;
169 : using ZoneEquipmentManager::UpdateZoneSizing;
170 : using ZoneTempPredictorCorrector::DetectOscillatingZoneTemp;
171 : using ZoneTempPredictorCorrector::ManageZoneAirUpdates;
172 :
173 : // SUBROUTINE PARAMETER DEFINITIONS:
174 : static constexpr std::string_view EndOfHeaderString("End of Data Dictionary"); // End of data dictionary marker
175 : static constexpr std::string_view EnvironmentStampFormatStr("{},{},{:7.2F},{:7.2F},{:7.2F},{:7.2F}\n"); // Format descriptor for environ stamp
176 :
177 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
178 : Real64 PriorTimeStep; // magnitude of time step for previous history terms
179 2568313 : Real64 ZoneTempChange(0.0); // change in zone air temperature from timestep t-1 to t
180 : int NodeNum;
181 : bool ReportDebug;
182 : int ZoneNum;
183 :
184 : bool DummyLogical;
185 :
186 2568313 : auto &AirLoopsSimOnce = state.dataHVACGlobal->AirLoopsSimOnce;
187 2568313 : auto &NumOfSysTimeStepsLastZoneTimeStep = state.dataHVACGlobal->NumOfSysTimeStepsLastZoneTimeStep;
188 2568313 : auto &SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
189 2568313 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
190 2568313 : auto &FirstTimeStepSysFlag = state.dataHVACGlobal->FirstTimeStepSysFlag;
191 2568313 : auto &ShortenTimeStepSys = state.dataHVACGlobal->ShortenTimeStepSys;
192 2568313 : auto &UseZoneTimeStepHistory = state.dataHVACGlobal->UseZoneTimeStepHistory;
193 2568313 : auto &NumOfSysTimeSteps = state.dataHVACGlobal->NumOfSysTimeSteps;
194 2568313 : auto &FracTimeStepZone = state.dataHVACGlobal->FracTimeStepZone;
195 2568313 : auto &LimitNumSysSteps = state.dataHVACGlobal->LimitNumSysSteps;
196 :
197 : // SYSTEM INITIALIZATION
198 2568313 : if (state.dataHVACMgr->TriggerGetAFN) {
199 771 : state.dataHVACMgr->TriggerGetAFN = false;
200 771 : DisplayString(state, "Initializing HVAC");
201 771 : state.afn->manage_balance(); // first call only gets input and returns.
202 : }
203 :
204 21013702 : for (auto &thisZoneHB : state.dataZoneTempPredictorCorrector->zoneHeatBalance) {
205 18445389 : thisZoneHB.ZT = thisZoneHB.MAT;
206 : // save for use with thermal comfort control models (Fang, Pierce, and KSU)
207 18445389 : thisZoneHB.ZTAV = 0.0;
208 18445389 : thisZoneHB.ZoneAirHumRatAvg = 0.0;
209 : }
210 2568313 : if (state.dataHeatBal->doSpaceHeatBalance) {
211 28308 : for (auto &thisSpaceHB : state.dataZoneTempPredictorCorrector->spaceHeatBalance) {
212 24264 : thisSpaceHB.ZT = thisSpaceHB.MAT;
213 : // save for use with thermal comfort control models (Fang, Pierce, and KSU)
214 24264 : thisSpaceHB.ZTAV = 0.0;
215 24264 : thisSpaceHB.ZoneAirHumRatAvg = 0.0;
216 : }
217 : }
218 2568313 : state.dataHeatBalFanSys->ZoneThermostatSetPointHiAver = 0.0;
219 2568313 : state.dataHeatBalFanSys->ZoneThermostatSetPointLoAver = 0.0;
220 2568313 : state.dataHVACMgr->PrintedWarmup = false;
221 2568313 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
222 37650 : state.dataContaminantBalance->OutdoorCO2 = GetCurrentScheduleValue(state, state.dataContaminantBalance->Contaminant.CO2OutdoorSchedPtr);
223 37650 : state.dataContaminantBalance->ZoneAirCO2Avg = 0.0;
224 : }
225 2568313 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
226 7089 : state.dataContaminantBalance->OutdoorGC =
227 7089 : GetCurrentScheduleValue(state, state.dataContaminantBalance->Contaminant.GenericContamOutdoorSchedPtr);
228 7089 : if (allocated(state.dataContaminantBalance->ZoneAirGCAvg)) state.dataContaminantBalance->ZoneAirGCAvg = 0.0;
229 : }
230 :
231 2568313 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHVACMgr->MyEnvrnFlag) {
232 6218 : AirLoopsSimOnce = false;
233 6218 : state.dataHVACMgr->MyEnvrnFlag = false;
234 6218 : NumOfSysTimeStepsLastZoneTimeStep = 1;
235 6218 : state.dataHVACGlobal->PreviousTimeStep = state.dataGlobal->TimeStepZone;
236 : }
237 2568313 : if (!state.dataGlobal->BeginEnvrnFlag) {
238 2562095 : state.dataHVACMgr->MyEnvrnFlag = true;
239 : }
240 :
241 2568313 : state.dataHeatBalFanSys->QRadSurfAFNDuct = 0.0;
242 2568313 : SysTimeElapsed = 0.0;
243 2568313 : TimeStepSys = state.dataGlobal->TimeStepZone;
244 2568313 : FirstTimeStepSysFlag = true;
245 2568313 : ShortenTimeStepSys = false;
246 2568313 : UseZoneTimeStepHistory = true;
247 2568313 : PriorTimeStep = state.dataGlobal->TimeStepZone;
248 2568313 : NumOfSysTimeSteps = 1;
249 2568313 : FracTimeStepZone = TimeStepSys / state.dataGlobal->TimeStepZone;
250 :
251 : bool anyEMSRan;
252 2568313 : ManageEMS(state, EMSManager::EMSCallFrom::BeginTimestepBeforePredictor, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point
253 :
254 2568313 : SetOutAirNodes(state);
255 :
256 2568313 : ManageRefrigeratedCaseRacks(state);
257 :
258 : // ZONE INITIALIZATION 'Get Zone Setpoints'
259 5136626 : ManageZoneAirUpdates(state,
260 : DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints,
261 : ZoneTempChange,
262 2568313 : ShortenTimeStepSys,
263 2568313 : UseZoneTimeStepHistory,
264 : PriorTimeStep);
265 2568313 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
266 95556 : ManageZoneContaminanUpdates(
267 95556 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
268 :
269 2568313 : ManageHybridVentilation(state);
270 :
271 2568313 : CalcAirFlowSimple(state);
272 2568313 : if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
273 96108 : state.afn->RollBackFlag = false;
274 96108 : state.afn->manage_balance(false);
275 : }
276 :
277 2568313 : SetHeatToReturnAirFlag(state);
278 :
279 21013702 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
280 18445389 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum);
281 18445389 : thisZoneHB.SysDepZoneLoadsLagged = thisZoneHB.SysDepZoneLoads;
282 18445389 : if (state.dataHeatBal->doSpaceHeatBalance) {
283 48528 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
284 : // SpaceHB ToDo: For now allocate by space volume frac
285 24264 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).SysDepZoneLoadsLagged =
286 24264 : thisZoneHB.SysDepZoneLoads * state.dataHeatBal->space(spaceNum).fracZoneVolume;
287 : }
288 : }
289 : }
290 :
291 2568313 : UpdateInternalGainValues(state, true, true);
292 :
293 5136626 : ManageZoneAirUpdates(
294 5136626 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep, ZoneTempChange, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
295 :
296 2568313 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
297 95556 : ManageZoneContaminanUpdates(
298 95556 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
299 :
300 2568313 : SimHVAC(state);
301 :
302 2568313 : if (state.dataGlobal->AnyIdealCondEntSetPointInModel && state.dataGlobal->MetersHaveBeenInitialized && !state.dataGlobal->WarmupFlag) {
303 384 : state.dataGlobal->RunOptCondEntTemp = true;
304 3500 : while (state.dataGlobal->RunOptCondEntTemp) {
305 1558 : SimHVAC(state);
306 : }
307 : }
308 :
309 2568313 : ManageWaterInits(state);
310 :
311 : // Only simulate once per zone timestep; must be after SimHVAC
312 2568313 : if (FirstTimeStepSysFlag && state.dataGlobal->MetersHaveBeenInitialized) {
313 1776765 : ManageDemand(state);
314 : }
315 :
316 2568313 : state.dataGlobal->BeginTimeStepFlag = false; // At this point, we have been through the first pass through SimHVAC so this needs to be set
317 :
318 5136626 : ManageZoneAirUpdates(
319 5136626 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep, ZoneTempChange, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
320 2568313 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
321 95556 : ManageZoneContaminanUpdates(
322 95556 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
323 :
324 2568313 : if (ZoneTempChange > state.dataConvergeParams->MaxZoneTempDiff && !state.dataGlobal->KickOffSimulation) {
325 : // determine value of adaptive system time step
326 : // model how many system timesteps we want in zone timestep
327 345401 : int ZTempTrendsNumSysSteps = int(ZoneTempChange / state.dataConvergeParams->MaxZoneTempDiff + 1.0); // add 1 for truncation
328 345401 : NumOfSysTimeSteps = min(ZTempTrendsNumSysSteps, LimitNumSysSteps);
329 : // then determine timestep length for even distribution, protect div by zero
330 345401 : if (NumOfSysTimeSteps > 0) TimeStepSys = state.dataGlobal->TimeStepZone / NumOfSysTimeSteps;
331 345401 : TimeStepSys = max(TimeStepSys, state.dataConvergeParams->MinTimeStepSys);
332 345401 : UseZoneTimeStepHistory = false;
333 345401 : ShortenTimeStepSys = true;
334 : } else {
335 2222912 : NumOfSysTimeSteps = 1;
336 2222912 : UseZoneTimeStepHistory = true;
337 : }
338 :
339 2568313 : if (UseZoneTimeStepHistory) state.dataHVACGlobal->PreviousTimeStep = state.dataGlobal->TimeStepZone;
340 5887100 : for (int SysTimestepLoop = 1; SysTimestepLoop <= NumOfSysTimeSteps; ++SysTimestepLoop) {
341 3318787 : if (state.dataGlobal->stopSimulation) break;
342 :
343 3318787 : if (TimeStepSys < state.dataGlobal->TimeStepZone) {
344 :
345 1055447 : ManageHybridVentilation(state);
346 1055447 : CalcAirFlowSimple(state, SysTimestepLoop);
347 1055447 : if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
348 62740 : state.afn->RollBackFlag = false;
349 62740 : state.afn->manage_balance(false);
350 : }
351 :
352 1055447 : UpdateInternalGainValues(state, true, true);
353 :
354 2110894 : ManageZoneAirUpdates(state,
355 : DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep,
356 : ZoneTempChange,
357 1055447 : ShortenTimeStepSys,
358 1055447 : UseZoneTimeStepHistory,
359 : PriorTimeStep);
360 :
361 1055447 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
362 48050 : ManageZoneContaminanUpdates(
363 48050 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
364 1055447 : SimHVAC(state);
365 :
366 1055447 : if (state.dataGlobal->AnyIdealCondEntSetPointInModel && state.dataGlobal->MetersHaveBeenInitialized && !state.dataGlobal->WarmupFlag) {
367 76 : state.dataGlobal->RunOptCondEntTemp = true;
368 1196 : while (state.dataGlobal->RunOptCondEntTemp) {
369 560 : SimHVAC(state);
370 : }
371 : }
372 :
373 1055447 : ManageWaterInits(state);
374 :
375 : // Need to set the flag back since we do not need to shift the temps back again in the correct step.
376 1055447 : ShortenTimeStepSys = false;
377 :
378 2110894 : ManageZoneAirUpdates(state,
379 : DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep,
380 : ZoneTempChange,
381 1055447 : ShortenTimeStepSys,
382 1055447 : UseZoneTimeStepHistory,
383 : PriorTimeStep);
384 1055447 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
385 48050 : ManageZoneContaminanUpdates(
386 48050 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
387 :
388 2110894 : ManageZoneAirUpdates(state,
389 : DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories,
390 : ZoneTempChange,
391 1055447 : ShortenTimeStepSys,
392 1055447 : UseZoneTimeStepHistory,
393 : PriorTimeStep);
394 1055447 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
395 48050 : ManageZoneContaminanUpdates(state,
396 : DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories,
397 24025 : ShortenTimeStepSys,
398 24025 : UseZoneTimeStepHistory,
399 : PriorTimeStep);
400 1055447 : state.dataHVACGlobal->PreviousTimeStep = TimeStepSys;
401 : }
402 :
403 3318787 : FracTimeStepZone = TimeStepSys / state.dataGlobal->TimeStepZone;
404 :
405 28499453 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
406 25180666 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
407 25180666 : thisZoneHB.ZTAV += thisZoneHB.ZT * FracTimeStepZone;
408 25180666 : thisZoneHB.ZoneAirHumRatAvg += thisZoneHB.ZoneAirHumRat * FracTimeStepZone;
409 25180666 : if (state.dataHeatBal->doSpaceHeatBalance) {
410 55068 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
411 27534 : auto &thisSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum);
412 27534 : thisSpaceHB.ZTAV += thisSpaceHB.ZT * FracTimeStepZone;
413 27534 : thisSpaceHB.ZoneAirHumRatAvg += thisSpaceHB.ZoneAirHumRat * FracTimeStepZone;
414 : }
415 : }
416 25180666 : if (state.dataContaminantBalance->Contaminant.CO2Simulation)
417 328207 : state.dataContaminantBalance->ZoneAirCO2Avg(ZoneNum) += state.dataContaminantBalance->ZoneAirCO2(ZoneNum) * FracTimeStepZone;
418 25180666 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation)
419 231201 : state.dataContaminantBalance->ZoneAirGCAvg(ZoneNum) += state.dataContaminantBalance->ZoneAirGC(ZoneNum) * FracTimeStepZone;
420 25180666 : if (state.dataZoneTempPredictorCorrector->NumOnOffCtrZone > 0) {
421 346719 : state.dataHeatBalFanSys->ZoneThermostatSetPointHiAver(ZoneNum) +=
422 346719 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum) * FracTimeStepZone;
423 346719 : state.dataHeatBalFanSys->ZoneThermostatSetPointLoAver(ZoneNum) +=
424 346719 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ZoneNum) * FracTimeStepZone;
425 : }
426 : }
427 :
428 3318787 : DetectOscillatingZoneTemp(state);
429 3318787 : UpdateZoneListAndGroupLoads(state); // Must be called before UpdateDataandReport(OutputProcessor::TimeStepType::TimeStepSystem)
430 3318787 : IceThermalStorage::UpdateIceFractions(state); // Update fraction of ice stored in TES
431 3318787 : ManageWater(state);
432 : // update electricity data for net, purchased, sold etc.
433 3318787 : DummyLogical = false;
434 3318787 : state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(state, false, DummyLogical, true);
435 :
436 : // Update the plant and condenser loop capacitance model temperature history.
437 3318787 : PlantManager::UpdateNodeThermalHistory(state);
438 :
439 3318787 : if (state.dataOutRptTab->displayHeatEmissionsSummary) {
440 1266396 : OutputReportTabular::CalcHeatEmissionReport(state);
441 : }
442 :
443 3318787 : ManageEMS(
444 6637574 : state, EMSManager::EMSCallFrom::EndSystemTimestepBeforeHVACReporting, anyEMSRan, ObjexxFCL::Optional_int_const()); // EMS calling point
445 :
446 : // This is where output processor data is updated for System Timestep reporting
447 3318787 : if (!state.dataGlobal->WarmupFlag) {
448 523087 : if (state.dataGlobal->DoOutputReporting && !state.dataGlobal->ZoneSizingCalc) {
449 391386 : CalcMoreNodeInfo(state);
450 391386 : CalculatePollution(state);
451 391386 : InitEnergyReports(state);
452 391386 : ReportSystemEnergyUse(state);
453 : }
454 523087 : if (state.dataGlobal->DoOutputReporting || (state.dataGlobal->ZoneSizingCalc && state.dataGlobal->CompLoadReportIsReq)) {
455 401522 : ReportAirHeatBalance(state);
456 401522 : if (state.dataGlobal->ZoneSizingCalc) GatherComponentLoadsHVAC(state);
457 : }
458 523087 : if (state.dataGlobal->DoOutputReporting) {
459 391386 : SystemReports::ReportVentilationLoads(state);
460 391386 : UpdateDataandReport(state, OutputProcessor::TimeStepType::System);
461 774031 : if (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::HVACSizeDesignDay ||
462 382645 : state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::HVACSizeRunPeriodDesign) {
463 8741 : if (state.dataHVACSizingSimMgr->hvacSizingSimulationManager)
464 8741 : state.dataHVACSizingSimMgr->hvacSizingSimulationManager->UpdateSizingLogsSystemStep(state);
465 : }
466 391386 : UpdateTabularReports(state, OutputProcessor::TimeStepType::System);
467 : }
468 523087 : if (state.dataGlobal->ZoneSizingCalc) {
469 131701 : UpdateZoneSizing(state, DataGlobalConstants::CallIndicator::DuringDay);
470 131701 : UpdateFacilitySizing(state, DataGlobalConstants::CallIndicator::DuringDay);
471 : }
472 523087 : EIRPlantLoopHeatPumps::EIRPlantLoopHeatPump::checkConcurrentOperation(state);
473 2795700 : } else if (!state.dataGlobal->KickOffSimulation && state.dataGlobal->DoOutputReporting && state.dataSysVars->ReportDuringWarmup) {
474 0 : if (state.dataGlobal->BeginDayFlag && !state.dataEnvrn->PrintEnvrnStampWarmupPrinted) {
475 0 : state.dataEnvrn->PrintEnvrnStampWarmup = true;
476 0 : state.dataEnvrn->PrintEnvrnStampWarmupPrinted = true;
477 : }
478 0 : if (!state.dataGlobal->BeginDayFlag) state.dataEnvrn->PrintEnvrnStampWarmupPrinted = false;
479 0 : if (state.dataEnvrn->PrintEnvrnStampWarmup) {
480 0 : if (state.dataReportFlag->PrintEndDataDictionary && state.dataGlobal->DoOutputReporting && !state.dataHVACMgr->PrintedWarmup) {
481 0 : print(state.files.eso, "{}\n", EndOfHeaderString);
482 0 : print(state.files.mtr, "{}\n", EndOfHeaderString);
483 0 : state.dataReportFlag->PrintEndDataDictionary = false;
484 : }
485 0 : if (state.dataGlobal->DoOutputReporting && !state.dataHVACMgr->PrintedWarmup) {
486 :
487 0 : print(state.files.eso,
488 : EnvironmentStampFormatStr,
489 : "1",
490 0 : "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
491 0 : state.dataEnvrn->Latitude,
492 0 : state.dataEnvrn->Longitude,
493 0 : state.dataEnvrn->TimeZoneNumber,
494 0 : state.dataEnvrn->Elevation);
495 0 : print(state.files.mtr,
496 : EnvironmentStampFormatStr,
497 : "1",
498 0 : "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
499 0 : state.dataEnvrn->Latitude,
500 0 : state.dataEnvrn->Longitude,
501 0 : state.dataEnvrn->TimeZoneNumber,
502 0 : state.dataEnvrn->Elevation);
503 0 : state.dataEnvrn->PrintEnvrnStampWarmup = false;
504 : }
505 0 : state.dataHVACMgr->PrintedWarmup = true;
506 : }
507 0 : if (!state.dataGlobal->DoingSizing) {
508 0 : CalcMoreNodeInfo(state);
509 : }
510 0 : UpdateDataandReport(state, OutputProcessor::TimeStepType::System);
511 0 : if (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::HVACSizeDesignDay ||
512 0 : state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::HVACSizeRunPeriodDesign) {
513 0 : if (state.dataHVACSizingSimMgr->hvacSizingSimulationManager)
514 0 : state.dataHVACSizingSimMgr->hvacSizingSimulationManager->UpdateSizingLogsSystemStep(state);
515 : }
516 2795700 : } else if (state.dataSysVars->UpdateDataDuringWarmupExternalInterface) { // added for FMI
517 0 : if (state.dataGlobal->BeginDayFlag && !state.dataEnvrn->PrintEnvrnStampWarmupPrinted) {
518 0 : state.dataEnvrn->PrintEnvrnStampWarmup = true;
519 0 : state.dataEnvrn->PrintEnvrnStampWarmupPrinted = true;
520 : }
521 0 : if (!state.dataGlobal->BeginDayFlag) state.dataEnvrn->PrintEnvrnStampWarmupPrinted = false;
522 0 : if (state.dataEnvrn->PrintEnvrnStampWarmup) {
523 0 : if (state.dataReportFlag->PrintEndDataDictionary && state.dataGlobal->DoOutputReporting && !state.dataHVACMgr->PrintedWarmup) {
524 0 : print(state.files.eso, "{}\n", EndOfHeaderString);
525 0 : print(state.files.mtr, "{}\n", EndOfHeaderString);
526 0 : state.dataReportFlag->PrintEndDataDictionary = false;
527 : }
528 0 : if (state.dataGlobal->DoOutputReporting && !state.dataHVACMgr->PrintedWarmup) {
529 0 : print(state.files.eso,
530 : EnvironmentStampFormatStr,
531 : "1",
532 0 : "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
533 0 : state.dataEnvrn->Latitude,
534 0 : state.dataEnvrn->Longitude,
535 0 : state.dataEnvrn->TimeZoneNumber,
536 0 : state.dataEnvrn->Elevation);
537 0 : print(state.files.mtr,
538 : EnvironmentStampFormatStr,
539 : "1",
540 0 : "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
541 0 : state.dataEnvrn->Latitude,
542 0 : state.dataEnvrn->Longitude,
543 0 : state.dataEnvrn->TimeZoneNumber,
544 0 : state.dataEnvrn->Elevation);
545 0 : state.dataEnvrn->PrintEnvrnStampWarmup = false;
546 : }
547 0 : state.dataHVACMgr->PrintedWarmup = true;
548 : }
549 0 : UpdateDataandReport(state, OutputProcessor::TimeStepType::System);
550 : }
551 3318787 : ManageEMS(
552 6637574 : state, EMSManager::EMSCallFrom::EndSystemTimestepAfterHVACReporting, anyEMSRan, ObjexxFCL::Optional_int_const()); // EMS calling point
553 : // UPDATE SYSTEM CLOCKS
554 3318787 : SysTimeElapsed += TimeStepSys;
555 :
556 3318787 : FirstTimeStepSysFlag = false;
557 : } // system time step loop (loops once if no downstepping)
558 :
559 21013702 : for (auto &thisZoneHB : state.dataZoneTempPredictorCorrector->zoneHeatBalance) {
560 18445389 : thisZoneHB.ZTAVComf = thisZoneHB.ZTAV;
561 18445389 : thisZoneHB.ZoneAirHumRatAvgComf = thisZoneHB.ZoneAirHumRatAvg;
562 : }
563 2568313 : if (state.dataHeatBal->doSpaceHeatBalance) {
564 28308 : for (auto &thisSpaceHB : state.dataZoneTempPredictorCorrector->spaceHeatBalance) {
565 24264 : thisSpaceHB.ZTAVComf = thisSpaceHB.ZTAV;
566 24264 : thisSpaceHB.ZoneAirHumRatAvgComf = thisSpaceHB.ZoneAirHumRatAvg;
567 : }
568 : }
569 :
570 5136626 : ManageZoneAirUpdates(state,
571 : DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories,
572 : ZoneTempChange,
573 2568313 : ShortenTimeStepSys,
574 2568313 : UseZoneTimeStepHistory,
575 : PriorTimeStep);
576 2568313 : if (state.dataContaminantBalance->Contaminant.SimulateContaminants)
577 95556 : ManageZoneContaminanUpdates(
578 95556 : state, DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
579 :
580 2568313 : NumOfSysTimeStepsLastZoneTimeStep = NumOfSysTimeSteps;
581 :
582 2568313 : UpdateDemandManagers(state);
583 :
584 : // DO FINAL UPDATE OF RECORD KEEPING VARIABLES
585 : // Report the Node Data to Aid in Debugging
586 2568313 : if (state.dataReportFlag->DebugOutput) {
587 0 : if (state.dataReportFlag->EvenDuringWarmup) {
588 0 : ReportDebug = true;
589 : } else {
590 0 : ReportDebug = !state.dataGlobal->WarmupFlag;
591 : }
592 0 : if ((ReportDebug) && (state.dataGlobal->DayOfSim > 0)) { // Report the node data
593 0 : if (size(state.dataLoopNodes->Node) > 0 && !state.dataHVACMgr->DebugNamesReported) {
594 0 : print(state.files.debug, "{}\n", "node # Name");
595 0 : for (NodeNum = 1; NodeNum <= isize(state.dataLoopNodes->Node); ++NodeNum) {
596 0 : print(state.files.debug, " {:3} {}\n", NodeNum, state.dataLoopNodes->NodeID(NodeNum));
597 : }
598 0 : state.dataHVACMgr->DebugNamesReported = true;
599 : }
600 0 : if (size(state.dataLoopNodes->Node) > 0) {
601 0 : print(state.files.debug, "\n\n Day of Sim Hour of Day Time\n");
602 0 : print(state.files.debug,
603 : "{:12}{:12} {:22.15N} \n",
604 0 : state.dataGlobal->DayOfSim,
605 0 : state.dataGlobal->HourOfDay,
606 0 : state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone);
607 0 : print(state.files.debug,
608 : "{}\n",
609 : "node # Temp MassMinAv MassMaxAv TempSP MassFlow MassMin MassMax MassSP Press "
610 0 : "Enthal HumRat Fluid Type");
611 : }
612 0 : for (NodeNum = 1; NodeNum <= isize(state.dataLoopNodes->Node); ++NodeNum) {
613 : static constexpr std::string_view Format_20{
614 : " {:3} {:8.2F} {:8.3F} {:8.3F} {:8.2F} {:13.2F} {:13.2F} {:13.2F} {:13.2F} {:#7.0F} {:11.2F} {:9.5F} {}\n"};
615 :
616 0 : print(state.files.debug,
617 : Format_20,
618 : NodeNum,
619 0 : state.dataLoopNodes->Node(NodeNum).Temp,
620 0 : state.dataLoopNodes->Node(NodeNum).MassFlowRateMinAvail,
621 0 : state.dataLoopNodes->Node(NodeNum).MassFlowRateMaxAvail,
622 0 : state.dataLoopNodes->Node(NodeNum).TempSetPoint,
623 0 : state.dataLoopNodes->Node(NodeNum).MassFlowRate,
624 0 : state.dataLoopNodes->Node(NodeNum).MassFlowRateMin,
625 0 : state.dataLoopNodes->Node(NodeNum).MassFlowRateMax,
626 0 : state.dataLoopNodes->Node(NodeNum).MassFlowRateSetPoint,
627 0 : state.dataLoopNodes->Node(NodeNum).Press,
628 0 : state.dataLoopNodes->Node(NodeNum).Enthalpy,
629 0 : state.dataLoopNodes->Node(NodeNum).HumRat,
630 0 : DataLoopNode::NodeFluidTypeNames[static_cast<int>(state.dataLoopNodes->Node(NodeNum).FluidType)]);
631 : }
632 : }
633 : }
634 2568313 : }
635 :
636 3626116 : void SimHVAC(EnergyPlusData &state)
637 : {
638 :
639 : // SUBROUTINE INFORMATION:
640 : // AUTHOR: Dan Fisher
641 : // DATE WRITTEN: April 1997
642 : // DATE MODIFIED: May 1998 (RKS,RDT)
643 :
644 : // PURPOSE OF THIS SUBROUTINE: Selects and calls the HVAC loop managers
645 :
646 : // METHODOLOGY EMPLOYED: Each loop manager is called or passed over
647 : // in succession based on the logical flags associated with the manager.
648 : // The logical flags are set in the manager routines and passed
649 : // as parameters to this routine. Each loop manager potentially
650 : // affects a different set of other loop managers.
651 :
652 : // Future development could involve specifying any number of user
653 : // selectable control schemes based on the logical flags used in
654 : // this default control algorithm.
655 :
656 : // Using/Aliasing
657 : using DataPlant::NumConvergenceHistoryTerms;
658 : using EMSManager::ManageEMS;
659 : using General::CreateSysTimeIntervalString;
660 : using NonZoneEquipmentManager::ManageNonZoneEquipment;
661 : using PlantCondLoopOperation::SetupPlantEMSActuators;
662 : using PlantManager::GetPlantInput;
663 : using PlantManager::GetPlantLoopData;
664 : using PlantManager::InitOneTimePlantSizingInfo;
665 : using PlantManager::ReInitPlantLoopsAtFirstHVACIteration;
666 : using PlantManager::SetupBranchControlTypes;
667 : using PlantManager::SetupInitialPlantCallingOrder;
668 : using PlantManager::SetupReports;
669 : using PlantUtilities::AnyPlantSplitterMixerLacksContinuity;
670 : using PlantUtilities::CheckForRunawayPlantTemps;
671 : using PlantUtilities::CheckPlantMixerSplitterConsistency;
672 : using PlantUtilities::SetAllPlantSimFlagsToValue;
673 : using SetPointManager::ManageSetPoints;
674 : using SystemAvailabilityManager::ManageSystemAvailability;
675 : using ZoneEquipmentManager::ManageZoneEquipment;
676 :
677 : // SUBROUTINE PARAMETER DEFINITIONS:
678 3626116 : bool constexpr SimWithPlantFlowUnlocked(false);
679 3626116 : bool constexpr SimWithPlantFlowLocked(true);
680 :
681 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
682 : bool FirstHVACIteration; // True when solution technique on first iteration
683 3626116 : auto &ErrCount = state.dataHVACMgr->ErrCount;
684 3626116 : auto &MaxErrCount = state.dataHVACMgr->MaxErrCount;
685 3626116 : auto &ErrEnvironmentName = state.dataHVACMgr->ErrEnvironmentName;
686 : int LoopNum;
687 :
688 : int AirSysNum;
689 : int StackDepth;
690 6264988 : std::string HistoryTrace;
691 : Real64 SlopeHumRat;
692 : Real64 SlopeMdot;
693 : Real64 SlopeTemps;
694 : Real64 AvgValue;
695 : bool FoundOscillationByDuplicate;
696 : int ZoneNum;
697 : int NodeIndex;
698 : bool MonotonicIncreaseFound;
699 : bool MonotonicDecreaseFound;
700 :
701 : static constexpr std::array<Real64, DataConvergParams::ConvergLogStackDepth> ConvergLogStackARR = {
702 : 0.0, -1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0};
703 3626116 : Real64 constexpr sum_ConvergLogStackARR(-45);
704 3626116 : Real64 constexpr square_sum_ConvergLogStackARR(2025);
705 3626116 : Real64 constexpr sum_square_ConvergLogStackARR(285);
706 :
707 3626116 : auto &SimZoneEquipmentFlag = state.dataHVACGlobal->SimZoneEquipmentFlag;
708 3626116 : auto &SimNonZoneEquipmentFlag = state.dataHVACGlobal->SimNonZoneEquipmentFlag;
709 3626116 : auto &SimAirLoopsFlag = state.dataHVACGlobal->SimAirLoopsFlag;
710 3626116 : auto &SimPlantLoopsFlag = state.dataHVACGlobal->SimPlantLoopsFlag;
711 3626116 : auto &SimElecCircuitsFlag = state.dataHVACGlobal->SimElecCircuitsFlag;
712 3626116 : auto &NumPrimaryAirSys = state.dataHVACGlobal->NumPrimaryAirSys;
713 3626116 : auto &DoSetPointTest = state.dataHVACGlobal->DoSetPointTest;
714 3626116 : auto &SetPointErrorFlag = state.dataHVACGlobal->SetPointErrorFlag;
715 :
716 : // Initialize all of the simulation flags to true for the first iteration
717 3626116 : SimZoneEquipmentFlag = true;
718 3626116 : SimNonZoneEquipmentFlag = true;
719 3626116 : SimAirLoopsFlag = true;
720 3626116 : SimPlantLoopsFlag = true;
721 3626116 : SimElecCircuitsFlag = true;
722 3626116 : FirstHVACIteration = true;
723 :
724 3626116 : if (state.dataAirLoop->AirLoopInputsFilled) {
725 6858357 : for (auto &e : state.dataAirLoop->AirLoopControlInfo) {
726 : // Reset air loop control info for cooling coil active flag (used in TU's for reheat air flow control)
727 4220254 : e.CoolingActiveFlag = false;
728 : // Reset air loop control info for heating coil active flag (used in OA controller for HX control)
729 4220254 : e.HeatingActiveFlag = false;
730 : // reset outside air system HX to off first time through
731 4220254 : e.HeatRecoveryBypass = true;
732 : // set HX check status flag to check for custom control in MixedAir.cc
733 4220254 : e.CheckHeatRecoveryBypassStatus = true;
734 : // set OA comp simulated flag to false
735 4220254 : e.OASysComponentsSimulated = false;
736 : // set economizer flow locked flag to false, will reset if custom HX control is used
737 4220254 : e.EconomizerFlowLocked = false;
738 : // set air loop resim flags for when heat recovery is used and air loop needs another iteration
739 4220254 : e.HeatRecoveryResimFlag = true;
740 4220254 : e.HeatRecoveryResimFlag2 = false;
741 4220254 : e.ResimAirLoopFlag = false;
742 : }
743 : }
744 :
745 : // This setups the reports for the Iteration variable that limits how many times
746 : // it goes through all of the HVAC managers before moving on.
747 : // The plant loop 'get inputs' and initialization are also done here in order to allow plant loop connected components
748 : // simulated by managers other than the plant manager to run correctly.
749 3626116 : state.dataHVACMgr->HVACManageIteration = 0;
750 3626116 : state.dataPlnt->PlantManageSubIterations = 0;
751 3626116 : state.dataPlnt->PlantManageHalfLoopCalls = 0;
752 3626116 : SetAllPlantSimFlagsToValue(state, true);
753 3626116 : if (!state.dataHVACMgr->SimHVACIterSetup) {
754 2313 : SetupOutputVariable(state,
755 : "HVAC System Solver Iteration Count",
756 : OutputProcessor::Unit::None,
757 771 : state.dataHVACMgr->HVACManageIteration,
758 : OutputProcessor::SOVTimeStepType::HVAC,
759 : OutputProcessor::SOVStoreType::Summed,
760 1542 : "SimHVAC");
761 2313 : SetupOutputVariable(state,
762 : "Air System Solver Iteration Count",
763 : OutputProcessor::Unit::None,
764 771 : state.dataHVACMgr->RepIterAir,
765 : OutputProcessor::SOVTimeStepType::HVAC,
766 : OutputProcessor::SOVStoreType::Summed,
767 1542 : "SimHVAC");
768 2313 : SetupOutputVariable(state,
769 : "Air System Relief Air Total Heat Loss Energy",
770 : OutputProcessor::Unit::J,
771 771 : state.dataHeatBal->SysTotalHVACReliefHeatLoss,
772 : OutputProcessor::SOVTimeStepType::HVAC,
773 : OutputProcessor::SOVStoreType::Summed,
774 1542 : "SimHVAC");
775 2313 : SetupOutputVariable(state,
776 : "HVAC System Total Heat Rejection Energy",
777 : OutputProcessor::Unit::J,
778 771 : state.dataHeatBal->SysTotalHVACRejectHeatLoss,
779 : OutputProcessor::SOVTimeStepType::HVAC,
780 : OutputProcessor::SOVStoreType::Summed,
781 1542 : "SimHVAC");
782 771 : ManageSetPoints(state); // need to call this before getting plant loop data so setpoint checks can complete okay
783 771 : GetPlantLoopData(state);
784 771 : GetPlantInput(state);
785 771 : SetupInitialPlantCallingOrder(state);
786 771 : SetupBranchControlTypes(state); // new routine to do away with input for branch control type
787 : // CALL CheckPlantLoopData
788 771 : SetupReports(state);
789 771 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
790 71 : SetupPlantEMSActuators(state);
791 : }
792 :
793 771 : if (state.dataPlnt->TotNumLoops > 0) {
794 1332 : SetupOutputVariable(state,
795 : "Plant Solver Sub Iteration Count",
796 : OutputProcessor::Unit::None,
797 444 : state.dataPlnt->PlantManageSubIterations,
798 : OutputProcessor::SOVTimeStepType::HVAC,
799 : OutputProcessor::SOVStoreType::Summed,
800 888 : "SimHVAC");
801 1332 : SetupOutputVariable(state,
802 : "Plant Solver Half Loop Calls Count",
803 : OutputProcessor::Unit::None,
804 444 : state.dataPlnt->PlantManageHalfLoopCalls,
805 : OutputProcessor::SOVTimeStepType::HVAC,
806 : OutputProcessor::SOVStoreType::Summed,
807 888 : "SimHVAC");
808 1553 : for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
809 : // init plant sizing numbers in main plant data structure
810 1109 : InitOneTimePlantSizingInfo(state, LoopNum);
811 : }
812 : }
813 771 : state.dataHVACMgr->SimHVACIterSetup = true;
814 : }
815 :
816 3626116 : if (state.dataGlobal->ZoneSizingCalc) {
817 987244 : ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipmentFlag, SimAirLoopsFlag);
818 : // need to call non zone equipment so water use zone gains can be included in sizing calcs
819 987244 : ManageNonZoneEquipment(state, FirstHVACIteration, SimNonZoneEquipmentFlag);
820 987244 : state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(state, FirstHVACIteration, SimElecCircuitsFlag, false);
821 987244 : return;
822 : }
823 :
824 : // Before the HVAC simulation, reset control flags and specified flow
825 : // rates that might have been set by the set point and availability
826 : // managers.
827 :
828 2638872 : ResetHVACControl(state);
829 :
830 : // Before the HVAC simulation, call ManageSetPoints to set all the HVAC
831 : // node setpoints
832 2638872 : bool anyEMSRan = false;
833 2638872 : ManageEMS(state, EMSManager::EMSCallFrom::BeforeHVACManagers, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point
834 :
835 2638872 : ManageSetPoints(state);
836 :
837 : // re-initialize plant loop and nodes.
838 2638872 : ReInitPlantLoopsAtFirstHVACIteration(state);
839 :
840 : // Before the HVAC simulation, call ManageSystemAvailability to set
841 : // the system on/off flags
842 2638872 : ManageSystemAvailability(state);
843 :
844 2638872 : ManageEMS(state, EMSManager::EMSCallFrom::AfterHVACManagers, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point
845 2638872 : ManageEMS(state, EMSManager::EMSCallFrom::HVACIterationLoop, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point id
846 :
847 : // first explicitly call each system type with FirstHVACIteration,
848 :
849 : // Manages the various component simulations
850 2638872 : SimSelectedEquipment(state,
851 : SimAirLoopsFlag,
852 : SimZoneEquipmentFlag,
853 : SimNonZoneEquipmentFlag,
854 : SimPlantLoopsFlag,
855 : SimElecCircuitsFlag,
856 : FirstHVACIteration,
857 : SimWithPlantFlowUnlocked);
858 :
859 : // Eventually, when all of the flags are set to false, the
860 : // simulation has converged for this system time step.
861 :
862 2638872 : SimPlantLoopsFlag = true;
863 2638872 : SetAllPlantSimFlagsToValue(state, true); // set so loop to simulate at least once on non-first hvac
864 :
865 2638872 : FirstHVACIteration = false;
866 :
867 : // then iterate among all systems after first HVAC iteration is over
868 :
869 : // Main iteration loop for HVAC. If any of the simulation flags are
870 : // true, then specific components must be resimulated.
871 11505046 : while ((SimAirLoopsFlag || SimZoneEquipmentFlag || SimNonZoneEquipmentFlag || SimPlantLoopsFlag || SimElecCircuitsFlag) &&
872 2956732 : (state.dataHVACMgr->HVACManageIteration <= state.dataConvergeParams->MaxIter)) {
873 :
874 2954721 : if (state.dataGlobal->stopSimulation) break;
875 :
876 2954721 : ManageEMS(state, EMSManager::EMSCallFrom::HVACIterationLoop, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point id
877 :
878 : // Manages the various component simulations
879 2954721 : SimSelectedEquipment(state,
880 : SimAirLoopsFlag,
881 : SimZoneEquipmentFlag,
882 : SimNonZoneEquipmentFlag,
883 : SimPlantLoopsFlag,
884 : SimElecCircuitsFlag,
885 : FirstHVACIteration,
886 : SimWithPlantFlowUnlocked);
887 :
888 : // Eventually, when all of the flags are set to false, the
889 : // simulation has converged for this system time step.
890 :
891 2954721 : UpdateZoneInletConvergenceLog(state);
892 :
893 2954721 : ++state.dataHVACMgr->HVACManageIteration; // Increment the iteration counter
894 :
895 2954721 : if (anyEMSRan && state.dataHVACMgr->HVACManageIteration <= 2) {
896 : // the calling point emsCallFromHVACIterationLoop is only effective for air loops if this while loop runs at least twice
897 177522 : SimAirLoopsFlag = true;
898 : }
899 2954721 : if (state.dataHVACMgr->HVACManageIteration < state.dataHVACGlobal->MinAirLoopIterationsAfterFirst) {
900 : // sequenced zone loads for airloops may require extra iterations depending upon zone equipment order and load distribution type
901 70019 : SimAirLoopsFlag = true;
902 70019 : SimZoneEquipmentFlag = true;
903 : }
904 : }
905 2638872 : if (state.dataGlobal->AnyPlantInModel) {
906 1423921 : if (AnyPlantSplitterMixerLacksContinuity(state)) {
907 : // rerun systems in a "Final flow lock/last iteration" mode
908 : // now call for one second to last plant simulation
909 7382 : SimAirLoopsFlag = false;
910 7382 : SimZoneEquipmentFlag = false;
911 7382 : SimNonZoneEquipmentFlag = false;
912 7382 : SimPlantLoopsFlag = true;
913 7382 : SimElecCircuitsFlag = false;
914 7382 : SimSelectedEquipment(state,
915 : SimAirLoopsFlag,
916 : SimZoneEquipmentFlag,
917 : SimNonZoneEquipmentFlag,
918 : SimPlantLoopsFlag,
919 : SimElecCircuitsFlag,
920 : FirstHVACIteration,
921 : SimWithPlantFlowUnlocked);
922 : // now call for all non-plant simulation, but with plant flow lock on
923 7382 : SimAirLoopsFlag = true;
924 7382 : SimZoneEquipmentFlag = true;
925 7382 : SimNonZoneEquipmentFlag = true;
926 7382 : SimPlantLoopsFlag = false;
927 7382 : SimElecCircuitsFlag = true;
928 7382 : SimSelectedEquipment(state,
929 : SimAirLoopsFlag,
930 : SimZoneEquipmentFlag,
931 : SimNonZoneEquipmentFlag,
932 : SimPlantLoopsFlag,
933 : SimElecCircuitsFlag,
934 : FirstHVACIteration,
935 : SimWithPlantFlowLocked);
936 7382 : UpdateZoneInletConvergenceLog(state);
937 : // now call for a last plant simulation
938 7382 : SimAirLoopsFlag = false;
939 7382 : SimZoneEquipmentFlag = false;
940 7382 : SimNonZoneEquipmentFlag = false;
941 7382 : SimPlantLoopsFlag = true;
942 7382 : SimElecCircuitsFlag = false;
943 7382 : SimSelectedEquipment(state,
944 : SimAirLoopsFlag,
945 : SimZoneEquipmentFlag,
946 : SimNonZoneEquipmentFlag,
947 : SimPlantLoopsFlag,
948 : SimElecCircuitsFlag,
949 : FirstHVACIteration,
950 : SimWithPlantFlowUnlocked);
951 : // now call for a last all non-plant simulation, but with plant flow lock on
952 7382 : SimAirLoopsFlag = true;
953 7382 : SimZoneEquipmentFlag = true;
954 7382 : SimNonZoneEquipmentFlag = true;
955 7382 : SimPlantLoopsFlag = false;
956 7382 : SimElecCircuitsFlag = true;
957 7382 : SimSelectedEquipment(state,
958 : SimAirLoopsFlag,
959 : SimZoneEquipmentFlag,
960 : SimNonZoneEquipmentFlag,
961 : SimPlantLoopsFlag,
962 : SimElecCircuitsFlag,
963 : FirstHVACIteration,
964 : SimWithPlantFlowLocked);
965 7382 : UpdateZoneInletConvergenceLog(state);
966 : }
967 : }
968 :
969 : // Test plant loop for errors
970 6302465 : for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
971 10990779 : for (DataPlant::LoopSideLocation LoopSide : DataPlant::LoopSideKeys) {
972 7327186 : CheckPlantMixerSplitterConsistency(state, LoopNum, LoopSide, FirstHVACIteration);
973 7327186 : CheckForRunawayPlantTemps(state, LoopNum, LoopSide);
974 : }
975 : }
976 :
977 2638872 : if ((state.dataHVACMgr->HVACManageIteration > state.dataConvergeParams->MaxIter) && (!state.dataGlobal->WarmupFlag)) {
978 290 : ++ErrCount;
979 290 : if (ErrCount < 15) {
980 110 : ErrEnvironmentName = state.dataEnvrn->EnvironmentName;
981 330 : ShowWarningError(state,
982 550 : format("SimHVAC: Maximum iterations ({}) exceeded for all HVAC loops, at {}, {} {}",
983 110 : state.dataConvergeParams->MaxIter,
984 110 : state.dataEnvrn->EnvironmentName,
985 110 : state.dataEnvrn->CurMnDy,
986 330 : CreateSysTimeIntervalString(state)));
987 110 : if (SimAirLoopsFlag) {
988 105 : ShowContinueError(state, "The solution for one or more of the Air Loop HVAC systems did not appear to converge");
989 : }
990 110 : if (SimZoneEquipmentFlag) {
991 18 : ShowContinueError(state, "The solution for zone HVAC equipment did not appear to converge");
992 : }
993 110 : if (SimNonZoneEquipmentFlag) {
994 0 : ShowContinueError(state, "The solution for non-zone equipment did not appear to converge");
995 : }
996 110 : if (SimPlantLoopsFlag) {
997 0 : ShowContinueError(state, "The solution for one or more plant systems did not appear to converge");
998 : }
999 110 : if (SimElecCircuitsFlag) {
1000 0 : ShowContinueError(state, "The solution for on-site electric generators did not appear to converge");
1001 : }
1002 110 : if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
1003 15 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on each max iteration exceeded.");
1004 : }
1005 110 : if (state.dataGlobal->DisplayExtraWarnings) {
1006 :
1007 0 : for (AirSysNum = 1; AirSysNum <= NumPrimaryAirSys; ++AirSysNum) {
1008 :
1009 0 : auto &arrayRef = state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACMassFlowNotConverged;
1010 0 : if (std::any_of(std::begin(arrayRef), std::end(arrayRef), [](bool i) { return i; })) {
1011 :
1012 0 : ShowContinueError(state,
1013 0 : "Air System Named = " + state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).AirLoopName +
1014 : " did not converge for mass flow rate");
1015 0 : ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
1016 0 : HistoryTrace = "";
1017 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1018 0 : HistoryTrace +=
1019 0 : format("{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACFlowDemandToSupplyTolValue[StackDepth]);
1020 : }
1021 :
1022 0 : ShowContinueError(state, "Demand-to-Supply interface mass flow rate check value iteration history trace: " + HistoryTrace);
1023 0 : HistoryTrace = "";
1024 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1025 0 : HistoryTrace += format(
1026 0 : "{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACFlowSupplyDeck1ToDemandTolValue[StackDepth]);
1027 : }
1028 0 : ShowContinueError(state,
1029 0 : "Supply-to-demand interface deck 1 mass flow rate check value iteration history trace: " + HistoryTrace);
1030 :
1031 0 : if (state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).NumSupplyNodes >= 2) {
1032 0 : HistoryTrace = "";
1033 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1034 0 : HistoryTrace +=
1035 0 : format("{:.6R},",
1036 0 : state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACFlowSupplyDeck2ToDemandTolValue[StackDepth]);
1037 : }
1038 0 : ShowContinueError(
1039 0 : state, "Supply-to-demand interface deck 2 mass flow rate check value iteration history trace: " + HistoryTrace);
1040 : }
1041 : } // mass flow rate not converged
1042 :
1043 0 : auto &arrayRef2 = state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACHumRatNotConverged;
1044 0 : if (std::any_of(std::begin(arrayRef2), std::end(arrayRef2), [](bool i) { return i; })) {
1045 :
1046 0 : ShowContinueError(state,
1047 0 : "Air System Named = " + state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).AirLoopName +
1048 : " did not converge for humidity ratio");
1049 0 : ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
1050 0 : HistoryTrace = "";
1051 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1052 0 : HistoryTrace +=
1053 0 : format("{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACHumDemandToSupplyTolValue[StackDepth]);
1054 : }
1055 0 : ShowContinueError(state, "Demand-to-Supply interface humidity ratio check value iteration history trace: " + HistoryTrace);
1056 0 : HistoryTrace = "";
1057 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1058 0 : HistoryTrace += format(
1059 0 : "{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACHumSupplyDeck1ToDemandTolValue[StackDepth]);
1060 : }
1061 0 : ShowContinueError(state,
1062 0 : "Supply-to-demand interface deck 1 humidity ratio check value iteration history trace: " + HistoryTrace);
1063 :
1064 0 : if (state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).NumSupplyNodes >= 2) {
1065 0 : HistoryTrace = "";
1066 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1067 0 : HistoryTrace +=
1068 0 : format("{:.6R},",
1069 0 : state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACHumSupplyDeck2ToDemandTolValue[StackDepth]);
1070 : }
1071 0 : ShowContinueError(
1072 0 : state, "Supply-to-demand interface deck 2 humidity ratio check value iteration history trace: " + HistoryTrace);
1073 : }
1074 : } // humidity ratio not converged
1075 :
1076 0 : auto &arrayRef3 = state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACTempNotConverged;
1077 0 : if (std::any_of(std::begin(arrayRef3), std::end(arrayRef3), [](bool i) { return i; })) {
1078 :
1079 0 : ShowContinueError(state,
1080 0 : "Air System Named = " + state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).AirLoopName +
1081 : " did not converge for temperature");
1082 0 : ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
1083 0 : HistoryTrace = "";
1084 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1085 0 : HistoryTrace +=
1086 0 : format("{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACTempDemandToSupplyTolValue[StackDepth]);
1087 : }
1088 0 : ShowContinueError(state, "Demand-to-Supply interface temperature check value iteration history trace: " + HistoryTrace);
1089 0 : HistoryTrace = "";
1090 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1091 0 : HistoryTrace += format(
1092 0 : "{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACTempSupplyDeck1ToDemandTolValue[StackDepth]);
1093 : }
1094 0 : ShowContinueError(state,
1095 0 : "Supply-to-demand interface deck 1 temperature check value iteration history trace: " + HistoryTrace);
1096 :
1097 0 : if (state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).NumSupplyNodes >= 2) {
1098 0 : HistoryTrace = "";
1099 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1100 0 : HistoryTrace +=
1101 0 : format("{:.6R},",
1102 0 : state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACTempSupplyDeck1ToDemandTolValue[StackDepth]);
1103 : }
1104 0 : ShowContinueError(state,
1105 0 : "Supply-to-demand interface deck 2 temperature check value iteration history trace: " + HistoryTrace);
1106 : }
1107 : } // Temps not converged
1108 :
1109 0 : auto &arrayRef4 = state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACEnergyNotConverged;
1110 0 : if (std::any_of(std::begin(arrayRef4), std::end(arrayRef4), [](bool i) { return i; })) {
1111 :
1112 0 : ShowContinueError(state,
1113 0 : "Air System Named = " + state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).AirLoopName +
1114 : " did not converge for energy");
1115 0 : ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
1116 0 : HistoryTrace = "";
1117 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1118 0 : HistoryTrace += format(
1119 0 : "{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACEnergyDemandToSupplyTolValue[StackDepth]);
1120 : }
1121 0 : ShowContinueError(state, "Demand-to-Supply interface energy check value iteration history trace: " + HistoryTrace);
1122 0 : HistoryTrace = "";
1123 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1124 0 : HistoryTrace += format(
1125 0 : "{:.6R},", state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACEnergySupplyDeck1ToDemandTolValue[StackDepth]);
1126 : }
1127 0 : ShowContinueError(state, "Supply-to-demand interface deck 1 energy check value iteration history trace: " + HistoryTrace);
1128 :
1129 0 : if (state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).NumSupplyNodes >= 2) {
1130 0 : HistoryTrace = "";
1131 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1132 0 : HistoryTrace +=
1133 0 : format("{:.6R},",
1134 0 : state.dataConvergeParams->AirLoopConvergence(AirSysNum).HVACEnergySupplyDeck2ToDemandTolValue[StackDepth]);
1135 : }
1136 0 : ShowContinueError(state, "Supply-to-demand interface deck 2 energy check value iteration history trace: " + HistoryTrace);
1137 : }
1138 : } // energy not converged
1139 :
1140 : } // loop over air loop systems
1141 :
1142 : // loop over zones and check for issues with zone inlet nodes
1143 0 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1144 :
1145 0 : for (NodeIndex = 1; NodeIndex <= state.dataConvergeParams->ZoneInletConvergence(ZoneNum).NumInletNodes; ++NodeIndex) {
1146 :
1147 0 : auto &humRatInletNode = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio;
1148 0 : auto &mdotInletNode = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate;
1149 0 : auto &inletTemp = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature;
1150 :
1151 : // Check humidity ratio
1152 0 : FoundOscillationByDuplicate = false;
1153 0 : MonotonicDecreaseFound = false;
1154 0 : MonotonicIncreaseFound = false;
1155 : // check for evidence of oscillation by identifying duplicates when latest value not equal to average
1156 0 : Real64 summation = 0.0;
1157 0 : summation = std::accumulate(humRatInletNode.begin(), humRatInletNode.end(), 0.0);
1158 0 : AvgValue = summation / double(DataConvergParams::ConvergLogStackDepth);
1159 0 : if (std::abs(humRatInletNode[0] - AvgValue) >
1160 : DataConvergParams::HVACHumRatOscillationToler) { // last iterate differs from average
1161 0 : FoundOscillationByDuplicate = false;
1162 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1163 0 : if (std::abs(humRatInletNode[0] - humRatInletNode[StackDepth]) < DataConvergParams::HVACHumRatOscillationToler) {
1164 0 : FoundOscillationByDuplicate = true;
1165 0 : ShowContinueError(
1166 : state,
1167 0 : format("Node named {} shows oscillating humidity ratio across iterations with a repeated value of {:.6R}",
1168 0 : state.dataLoopNodes->NodeID(
1169 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1170 0 : humRatInletNode[0]));
1171 0 : break;
1172 : }
1173 : }
1174 0 : if (!FoundOscillationByDuplicate) {
1175 :
1176 0 : auto humRatInletNodDotProd = std::inner_product(
1177 0 : std::begin(ConvergLogStackARR), std::end(ConvergLogStackARR), std::begin(humRatInletNode), 0.0);
1178 0 : Real64 summation2 = 0.0;
1179 0 : summation2 = std::accumulate(humRatInletNode.begin(), humRatInletNode.end(), 0.0);
1180 0 : SlopeHumRat =
1181 0 : (sum_ConvergLogStackARR * summation2 - double(DataConvergParams::ConvergLogStackDepth) * humRatInletNodDotProd) /
1182 : (square_sum_ConvergLogStackARR - double(DataConvergParams::ConvergLogStackDepth) * sum_square_ConvergLogStackARR);
1183 0 : if (std::abs(SlopeHumRat) > DataConvergParams::HVACHumRatSlopeToler) {
1184 :
1185 0 : if (SlopeHumRat < 0.0) { // check for monotonic decrease
1186 0 : MonotonicDecreaseFound = true;
1187 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1188 0 : if (humRatInletNode[StackDepth - 1] > humRatInletNode[StackDepth]) {
1189 0 : MonotonicDecreaseFound = false;
1190 0 : break;
1191 : }
1192 : }
1193 0 : if (MonotonicDecreaseFound) {
1194 0 : ShowContinueError(
1195 : state,
1196 0 : format("Node named {} shows monotonically decreasing humidity ratio with a trend "
1197 : "rate across iterations of {:.6R} [ kg-water/kg-dryair/iteration]",
1198 0 : state.dataLoopNodes->NodeID(
1199 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1200 0 : SlopeHumRat));
1201 : }
1202 : } else { // check for monotonic increase
1203 0 : MonotonicIncreaseFound = true;
1204 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1205 0 : if (humRatInletNode[StackDepth - 1] < humRatInletNode[StackDepth]) {
1206 0 : MonotonicIncreaseFound = false;
1207 0 : break;
1208 : }
1209 : }
1210 0 : if (MonotonicIncreaseFound) {
1211 0 : ShowContinueError(
1212 : state,
1213 0 : format("Node named {} shows monotonically increasing humidity ratio with a trend "
1214 : "rate across iterations of {:.6R} [ kg-water/kg-dryair/iteration]",
1215 0 : state.dataLoopNodes->NodeID(
1216 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1217 0 : SlopeHumRat));
1218 : }
1219 : }
1220 : } // significant slope in iterates
1221 : } // no osciallation
1222 : } // last value does not equal average of stack.
1223 :
1224 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1225 0 : HistoryTrace = "";
1226 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1227 0 : HistoryTrace += format("{:.6R},", humRatInletNode[StackDepth]);
1228 : }
1229 0 : ShowContinueError(
1230 : state,
1231 0 : "Node named " +
1232 0 : state.dataLoopNodes->NodeID(
1233 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum) +
1234 0 : " humidity ratio [kg-water/kg-dryair] iteration history trace (most recent first): " + HistoryTrace);
1235 : } // need to report trace
1236 : // end humidity ratio
1237 :
1238 : // Check Mass flow rate
1239 0 : FoundOscillationByDuplicate = false;
1240 0 : MonotonicDecreaseFound = false;
1241 0 : MonotonicIncreaseFound = false;
1242 : // check for evidence of oscillation by identify duplicates when latest value not equal to average
1243 0 : Real64 summation2 = 0.0;
1244 0 : summation2 = std::accumulate(mdotInletNode.begin(), mdotInletNode.end(), 0.0);
1245 0 : AvgValue = summation2 / double(DataConvergParams::ConvergLogStackDepth);
1246 0 : if (std::abs(mdotInletNode[0] - AvgValue) >
1247 : DataConvergParams::HVACFlowRateOscillationToler) { // last iterate differs from average
1248 0 : FoundOscillationByDuplicate = false;
1249 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1250 0 : if (std::abs(mdotInletNode[0] - mdotInletNode[StackDepth]) < DataConvergParams::HVACFlowRateOscillationToler) {
1251 0 : FoundOscillationByDuplicate = true;
1252 0 : ShowContinueError(
1253 : state,
1254 0 : format("Node named {} shows oscillating mass flow rate across iterations with a repeated value of {:.6R}",
1255 0 : state.dataLoopNodes->NodeID(
1256 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1257 0 : mdotInletNode[0]));
1258 0 : break;
1259 : }
1260 : }
1261 0 : if (!FoundOscillationByDuplicate) {
1262 :
1263 : auto humRatInletNodDotProd =
1264 0 : std::inner_product(std::begin(ConvergLogStackARR), std::end(ConvergLogStackARR), std::begin(mdotInletNode), 0.0);
1265 0 : Real64 summation3 = 0.0;
1266 0 : summation3 = std::accumulate(mdotInletNode.begin(), mdotInletNode.end(), 0.0);
1267 0 : SlopeMdot =
1268 0 : (sum_ConvergLogStackARR * summation3 - double(DataConvergParams::ConvergLogStackDepth) * humRatInletNodDotProd) /
1269 : (square_sum_ConvergLogStackARR - double(DataConvergParams::ConvergLogStackDepth) * sum_square_ConvergLogStackARR);
1270 0 : if (std::abs(SlopeMdot) > DataConvergParams::HVACFlowRateSlopeToler) {
1271 0 : if (SlopeMdot < 0.0) { // check for monotonic decrease
1272 0 : MonotonicDecreaseFound = true;
1273 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1274 0 : if (mdotInletNode[StackDepth - 1] > mdotInletNode[StackDepth]) {
1275 0 : MonotonicDecreaseFound = false;
1276 0 : break;
1277 : }
1278 : }
1279 0 : if (MonotonicDecreaseFound) {
1280 0 : ShowContinueError(
1281 : state,
1282 0 : format("Node named {} shows monotonically decreasing mass flow rate with a trend "
1283 : "rate across iterations of {:.6R} [kg/s/iteration]",
1284 0 : state.dataLoopNodes->NodeID(
1285 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1286 0 : SlopeMdot));
1287 : }
1288 : } else { // check for monotonic increase
1289 0 : MonotonicIncreaseFound = true;
1290 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1291 0 : if (mdotInletNode[StackDepth - 1] < mdotInletNode[StackDepth]) {
1292 0 : MonotonicIncreaseFound = false;
1293 0 : break;
1294 : }
1295 : }
1296 0 : if (MonotonicIncreaseFound) {
1297 0 : ShowContinueError(
1298 : state,
1299 0 : format("Node named {} shows monotonically increasing mass flow rate with a trend "
1300 : "rate across iterations of {:.6R} [kg/s/iteration]",
1301 0 : state.dataLoopNodes->NodeID(
1302 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1303 0 : SlopeMdot));
1304 : }
1305 : }
1306 : } // significant slope in iterates
1307 : } // no oscillation
1308 : } // last value does not equal average of stack.
1309 :
1310 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1311 0 : HistoryTrace = "";
1312 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1313 0 : HistoryTrace += format("{:.6R},", mdotInletNode[StackDepth]);
1314 : }
1315 0 : ShowContinueError(state,
1316 0 : "Node named " +
1317 0 : state.dataLoopNodes->NodeID(
1318 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum) +
1319 0 : " mass flow rate [kg/s] iteration history trace (most recent first): " + HistoryTrace);
1320 : } // need to report trace
1321 : // end mass flow rate
1322 :
1323 : // Check Temperatures
1324 0 : FoundOscillationByDuplicate = false;
1325 0 : MonotonicDecreaseFound = false;
1326 0 : MonotonicIncreaseFound = false;
1327 : // check for evidence of oscillation by identify duplicates when latest value not equal to average
1328 0 : Real64 summation3 = 0.0;
1329 0 : summation3 = std::accumulate(inletTemp.begin(), inletTemp.end(), 0.0);
1330 0 : AvgValue = summation3 / double(DataConvergParams::ConvergLogStackDepth);
1331 0 : if (std::abs(inletTemp[0] - AvgValue) >
1332 : DataConvergParams::HVACTemperatureOscillationToler) { // last iterate differs from average
1333 0 : FoundOscillationByDuplicate = false;
1334 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1335 0 : if (std::abs(inletTemp[0] - inletTemp[StackDepth]) < DataConvergParams::HVACTemperatureOscillationToler) {
1336 0 : FoundOscillationByDuplicate = true;
1337 0 : ShowContinueError(
1338 : state,
1339 0 : format("Node named {} shows oscillating temperatures across iterations with a repeated value of {:.6R}",
1340 0 : state.dataLoopNodes->NodeID(
1341 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1342 0 : inletTemp[0]));
1343 0 : break;
1344 : }
1345 : }
1346 0 : if (!FoundOscillationByDuplicate) {
1347 :
1348 : auto inletTempDotProd =
1349 0 : std::inner_product(std::begin(ConvergLogStackARR), std::end(ConvergLogStackARR), std::begin(inletTemp), 0.0);
1350 :
1351 0 : Real64 summation4 = 0.0;
1352 0 : summation4 = std::accumulate(inletTemp.begin(), inletTemp.end(), 0.0);
1353 0 : SlopeTemps =
1354 0 : (sum_ConvergLogStackARR * summation4 - double(DataConvergParams::ConvergLogStackDepth) * inletTempDotProd) /
1355 : (square_sum_ConvergLogStackARR - double(DataConvergParams::ConvergLogStackDepth) * sum_square_ConvergLogStackARR);
1356 0 : if (std::abs(SlopeTemps) > DataConvergParams::HVACTemperatureSlopeToler) {
1357 0 : if (SlopeTemps < 0.0) { // check for monotonic decrease
1358 0 : MonotonicDecreaseFound = true;
1359 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1360 0 : if (inletTemp[StackDepth - 1] > inletTemp[StackDepth]) {
1361 0 : MonotonicDecreaseFound = false;
1362 0 : break;
1363 : }
1364 : }
1365 0 : if (MonotonicDecreaseFound) {
1366 0 : ShowContinueError(
1367 : state,
1368 0 : format("Node named {} shows monotonically decreasing temperature with a trend rate "
1369 : "across iterations of {:.4R} [C/iteration]",
1370 0 : state.dataLoopNodes->NodeID(
1371 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1372 0 : SlopeTemps));
1373 : }
1374 : } else { // check for monotonic increase
1375 0 : MonotonicIncreaseFound = true;
1376 0 : for (StackDepth = 1; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1377 0 : if (inletTemp[StackDepth - 1] < inletTemp[StackDepth]) {
1378 0 : MonotonicIncreaseFound = false;
1379 0 : break;
1380 : }
1381 : }
1382 0 : if (MonotonicIncreaseFound) {
1383 0 : ShowContinueError(
1384 : state,
1385 0 : format("Node named {} shows monotonically increasing temperatures with a trend "
1386 : "rate across iterations of {:.4R} [C/iteration]",
1387 0 : state.dataLoopNodes->NodeID(
1388 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum),
1389 0 : SlopeTemps));
1390 : }
1391 : }
1392 : } // significant slope in iterates
1393 : } // no osciallation
1394 : } // last value does not equal average of stack.
1395 :
1396 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1397 0 : HistoryTrace = "";
1398 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1399 0 : HistoryTrace += format("{:.6R},", inletTemp[StackDepth]);
1400 : }
1401 0 : ShowContinueError(state,
1402 0 : "Node named " +
1403 0 : state.dataLoopNodes->NodeID(
1404 0 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum) +
1405 0 : " temperature [C] iteration history trace (most recent first): " + HistoryTrace);
1406 : } // need to report trace
1407 : // end Temperature checks
1408 :
1409 : } // loop over zone inlet nodes
1410 : } // loop over zones
1411 :
1412 0 : for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
1413 :
1414 0 : if (state.dataConvergeParams->PlantConvergence(LoopNum).PlantMassFlowNotConverged) {
1415 0 : ShowContinueError(state,
1416 0 : "Plant System Named = " + state.dataPlnt->PlantLoop(LoopNum).Name + " did not converge for mass flow rate");
1417 0 : ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
1418 0 : HistoryTrace = "";
1419 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1420 0 : HistoryTrace +=
1421 0 : format("{:.6R},", state.dataConvergeParams->PlantConvergence(LoopNum).PlantFlowDemandToSupplyTolValue[StackDepth]);
1422 : }
1423 0 : ShowContinueError(state, "Demand-to-Supply interface mass flow rate check value iteration history trace: " + HistoryTrace);
1424 0 : HistoryTrace = "";
1425 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1426 0 : HistoryTrace +=
1427 0 : format("{:.6R},", state.dataConvergeParams->PlantConvergence(LoopNum).PlantFlowSupplyToDemandTolValue[StackDepth]);
1428 : }
1429 0 : ShowContinueError(state, "Supply-to-Demand interface mass flow rate check value iteration history trace: " + HistoryTrace);
1430 :
1431 : // now work with history logs for mass flow to detect issues
1432 0 : for (auto ThisLoopSide : DataPlant::LoopSideKeys) {
1433 :
1434 0 : auto &mdotHistInletNode = state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).InletNode.MassFlowRateHistory;
1435 0 : auto &mdotHistOutletNode = state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).OutletNode.MassFlowRateHistory;
1436 :
1437 : // loop side inlet node
1438 0 : FoundOscillationByDuplicate = false;
1439 0 : MonotonicDecreaseFound = false;
1440 0 : MonotonicIncreaseFound = false;
1441 0 : AvgValue = sum(mdotHistInletNode) / double(NumConvergenceHistoryTerms);
1442 0 : if (std::abs(mdotHistInletNode(1) - AvgValue) > DataConvergParams::PlantFlowRateOscillationToler) {
1443 0 : FoundOscillationByDuplicate = false;
1444 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1445 0 : if (std::abs(mdotHistInletNode(1) - mdotHistInletNode(StackDepth)) <
1446 : DataConvergParams::PlantFlowRateOscillationToler) {
1447 0 : FoundOscillationByDuplicate = true;
1448 0 : ShowContinueError(
1449 : state,
1450 0 : format("Node named {} shows oscillating flow rates across iterations with a repeated value of {:.7R}",
1451 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn,
1452 0 : mdotHistInletNode(1)));
1453 0 : break;
1454 : }
1455 : }
1456 : }
1457 0 : if (!FoundOscillationByDuplicate) {
1458 :
1459 0 : Real64 mdotHistInletNodeDotProd = std::inner_product(
1460 0 : std::begin(ConvergenceHistoryARR), std::end(ConvergenceHistoryARR), std::begin(mdotHistInletNode), 0.0);
1461 :
1462 0 : SlopeMdot =
1463 0 : (sum_ConvergenceHistoryARR * sum(mdotHistInletNode) -
1464 0 : double(NumConvergenceHistoryTerms) * mdotHistInletNodeDotProd) /
1465 : (square_sum_ConvergenceHistoryARR - double(NumConvergenceHistoryTerms) * sum_square_ConvergenceHistoryARR);
1466 0 : if (std::abs(SlopeMdot) > DataConvergParams::PlantFlowRateSlopeToler) {
1467 0 : if (SlopeMdot < 0.0) { // check for monotonic decrease
1468 0 : MonotonicDecreaseFound = true;
1469 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1470 0 : if (mdotHistInletNode(StackDepth - 1) > mdotHistInletNode(StackDepth)) {
1471 0 : MonotonicDecreaseFound = false;
1472 0 : break;
1473 : }
1474 : }
1475 0 : if (MonotonicDecreaseFound) {
1476 0 : ShowContinueError(state,
1477 0 : format("Node named {} shows monotonically decreasing mass flow rate with a trend "
1478 : "rate across iterations of {:.7R} [kg/s/iteration]",
1479 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn,
1480 0 : SlopeMdot));
1481 : }
1482 : } else { // check for monotonic increase
1483 0 : MonotonicIncreaseFound = true;
1484 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1485 0 : if (mdotHistInletNode(StackDepth - 1) < mdotHistInletNode(StackDepth)) {
1486 0 : MonotonicIncreaseFound = false;
1487 0 : break;
1488 : }
1489 : }
1490 0 : if (MonotonicIncreaseFound) {
1491 0 : ShowContinueError(state,
1492 0 : format("Node named {} shows monotonically increasing mass flow rate with a trend "
1493 : "rate across iterations of {:.7R} [kg/s/iteration]",
1494 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn,
1495 0 : SlopeMdot));
1496 : }
1497 : }
1498 : } // significant slope found
1499 : } // no oscillation found
1500 :
1501 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1502 0 : HistoryTrace = "";
1503 0 : for (StackDepth = 1; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1504 0 : HistoryTrace += format("{:.7R},", mdotHistInletNode(StackDepth));
1505 : }
1506 0 : ShowContinueError(state,
1507 0 : "Node named " + state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn +
1508 0 : " mass flow rate [kg/s] iteration history trace (most recent first): " + HistoryTrace);
1509 : } // need to report trace
1510 : // end of inlet node
1511 :
1512 : // loop side outlet node
1513 0 : FoundOscillationByDuplicate = false;
1514 0 : MonotonicDecreaseFound = false;
1515 0 : MonotonicIncreaseFound = false;
1516 0 : AvgValue = sum(mdotHistOutletNode) / double(NumConvergenceHistoryTerms);
1517 0 : if (std::abs(mdotHistOutletNode(1) - AvgValue) > DataConvergParams::PlantFlowRateOscillationToler) {
1518 0 : FoundOscillationByDuplicate = false;
1519 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1520 0 : if (std::abs(mdotHistOutletNode(1) - mdotHistOutletNode(StackDepth)) <
1521 : DataConvergParams::PlantFlowRateOscillationToler) {
1522 0 : FoundOscillationByDuplicate = true;
1523 0 : ShowContinueError(
1524 : state,
1525 0 : format("Node named {} shows oscillating flow rates across iterations with a repeated value of {:.7R}",
1526 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut,
1527 0 : mdotHistOutletNode(1)));
1528 0 : break;
1529 : }
1530 : }
1531 : }
1532 0 : if (!FoundOscillationByDuplicate) {
1533 :
1534 0 : Real64 mdotHistOutletNodeDotProd = std::inner_product(
1535 0 : std::begin(ConvergenceHistoryARR), std::end(ConvergenceHistoryARR), std::begin(mdotHistOutletNode), 0.0);
1536 :
1537 0 : SlopeMdot =
1538 0 : (sum_ConvergenceHistoryARR * sum(mdotHistOutletNode) -
1539 0 : double(NumConvergenceHistoryTerms) * mdotHistOutletNodeDotProd) /
1540 : (square_sum_ConvergenceHistoryARR - double(NumConvergenceHistoryTerms) * sum_square_ConvergenceHistoryARR);
1541 0 : if (std::abs(SlopeMdot) > DataConvergParams::PlantFlowRateSlopeToler) {
1542 0 : if (SlopeMdot < 0.0) { // check for monotonic decrease
1543 0 : MonotonicDecreaseFound = true;
1544 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1545 0 : if (mdotHistOutletNode(StackDepth - 1) > mdotHistOutletNode(StackDepth)) {
1546 0 : MonotonicDecreaseFound = false;
1547 0 : break;
1548 : }
1549 : }
1550 0 : if (MonotonicDecreaseFound) {
1551 0 : ShowContinueError(state,
1552 0 : format("Node named {} shows monotonically decreasing mass flow rate with a trend "
1553 : "rate across iterations of {:.7R} [kg/s/iteration]",
1554 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut,
1555 0 : SlopeMdot));
1556 : }
1557 : } else { // check for monotonic increase
1558 0 : MonotonicIncreaseFound = true;
1559 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1560 0 : if (mdotHistOutletNode(StackDepth - 1) < mdotHistOutletNode(StackDepth)) {
1561 0 : MonotonicIncreaseFound = false;
1562 0 : break;
1563 : }
1564 : }
1565 0 : if (MonotonicIncreaseFound) {
1566 0 : ShowContinueError(state,
1567 0 : format("Node named {} shows monotonically increasing mass flow rate with a trend "
1568 : "rate across iterations of {:.7R} [kg/s/iteration]",
1569 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut,
1570 0 : SlopeMdot));
1571 : }
1572 : }
1573 : } // significant slope found
1574 : } // no oscillation found
1575 :
1576 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1577 0 : HistoryTrace = "";
1578 0 : for (StackDepth = 1; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1579 0 : HistoryTrace += format("{:.7R},", mdotHistOutletNode(StackDepth));
1580 : }
1581 0 : ShowContinueError(state,
1582 0 : "Node named " + state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut +
1583 0 : " mass flow rate [kg/s] iteration history trace (most recent first): " + HistoryTrace);
1584 : } // need to report trace
1585 : // end of Outlet node
1586 :
1587 : } // plant loop sides
1588 :
1589 : } // mass flow not converged
1590 :
1591 0 : if (state.dataConvergeParams->PlantConvergence(LoopNum).PlantTempNotConverged) {
1592 0 : ShowContinueError(state,
1593 0 : "Plant System Named = " + state.dataPlnt->PlantLoop(LoopNum).Name + " did not converge for temperature");
1594 0 : ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
1595 0 : HistoryTrace = "";
1596 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1597 0 : HistoryTrace +=
1598 0 : format("{:.6R},", state.dataConvergeParams->PlantConvergence(LoopNum).PlantTempDemandToSupplyTolValue[StackDepth]);
1599 : }
1600 0 : ShowContinueError(state, "Demand-to-Supply interface temperature check value iteration history trace: " + HistoryTrace);
1601 0 : HistoryTrace = "";
1602 0 : for (StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
1603 0 : HistoryTrace +=
1604 0 : format("{:.6R},", state.dataConvergeParams->PlantConvergence(LoopNum).PlantTempSupplyToDemandTolValue[StackDepth]);
1605 : }
1606 0 : ShowContinueError(state, "Supply-to-Demand interface temperature check value iteration history trace: " + HistoryTrace);
1607 :
1608 : // now work with history logs for mass flow to detect issues
1609 0 : for (auto ThisLoopSide : DataPlant::LoopSideKeys) {
1610 :
1611 0 : auto &tempHistInletNode = state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).InletNode.TemperatureHistory;
1612 0 : auto &tempHistOutletNode = state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).OutletNode.TemperatureHistory;
1613 :
1614 : // loop side inlet node
1615 0 : FoundOscillationByDuplicate = false;
1616 0 : MonotonicDecreaseFound = false;
1617 0 : MonotonicIncreaseFound = false;
1618 0 : AvgValue = sum(tempHistInletNode) / double(NumConvergenceHistoryTerms);
1619 0 : if (std::abs(tempHistInletNode(1) - AvgValue) > DataConvergParams::PlantTemperatureOscillationToler) {
1620 0 : FoundOscillationByDuplicate = false;
1621 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1622 0 : if (std::abs(tempHistInletNode(1) - tempHistInletNode(StackDepth)) <
1623 : DataConvergParams::PlantTemperatureOscillationToler) {
1624 0 : FoundOscillationByDuplicate = true;
1625 0 : ShowContinueError(
1626 : state,
1627 0 : format("Node named {} shows oscillating temperatures across iterations with a repeated value of {:.5R}",
1628 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn,
1629 0 : tempHistInletNode(1)));
1630 0 : break;
1631 : }
1632 : }
1633 : }
1634 0 : if (!FoundOscillationByDuplicate) {
1635 :
1636 0 : Real64 tempHistInletNodeDotProd = std::inner_product(
1637 0 : std::begin(ConvergenceHistoryARR), std::end(ConvergenceHistoryARR), std::begin(tempHistInletNode), 0.0);
1638 :
1639 0 : SlopeTemps =
1640 0 : (sum_ConvergenceHistoryARR * sum(tempHistInletNode) -
1641 0 : double(NumConvergenceHistoryTerms) * tempHistInletNodeDotProd) /
1642 : (square_sum_ConvergenceHistoryARR - double(NumConvergenceHistoryTerms) * sum_square_ConvergenceHistoryARR);
1643 0 : if (std::abs(SlopeTemps) > DataConvergParams::PlantTemperatureSlopeToler) {
1644 0 : if (SlopeTemps < 0.0) { // check for monotonic decrease
1645 0 : MonotonicDecreaseFound = true;
1646 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1647 0 : if (tempHistInletNode(StackDepth - 1) > tempHistInletNode(StackDepth)) {
1648 0 : MonotonicDecreaseFound = false;
1649 0 : break;
1650 : }
1651 : }
1652 0 : if (MonotonicDecreaseFound) {
1653 0 : ShowContinueError(state,
1654 0 : format("Node named {} shows monotonically decreasing temperatures with a trend "
1655 : "rate across iterations of {:.5R} [C/iteration]",
1656 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn,
1657 0 : SlopeTemps));
1658 : }
1659 : } else { // check for monotonic increase
1660 0 : MonotonicIncreaseFound = true;
1661 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1662 0 : if (tempHistInletNode(StackDepth - 1) < tempHistInletNode(StackDepth)) {
1663 0 : MonotonicIncreaseFound = false;
1664 0 : break;
1665 : }
1666 : }
1667 0 : if (MonotonicIncreaseFound) {
1668 0 : ShowContinueError(state,
1669 0 : format("Node named {} shows monotonically increasing temperatures with a trend "
1670 : "rate across iterations of {:.5R} [C/iteration]",
1671 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn,
1672 0 : SlopeTemps));
1673 : }
1674 : }
1675 : } // significant slope found
1676 : } // no oscillation found
1677 :
1678 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1679 0 : HistoryTrace = "";
1680 0 : for (StackDepth = 1; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1681 0 : HistoryTrace += format("{:.5R},", tempHistInletNode(StackDepth));
1682 : }
1683 0 : ShowContinueError(state,
1684 0 : "Node named " + state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameIn +
1685 0 : " temperature [C] iteration history trace (most recent first): " + HistoryTrace);
1686 : } // need to report trace
1687 : // end of inlet node
1688 :
1689 : // loop side outlet node
1690 0 : FoundOscillationByDuplicate = false;
1691 0 : MonotonicDecreaseFound = false;
1692 0 : MonotonicIncreaseFound = false;
1693 0 : AvgValue = sum(tempHistOutletNode) / double(NumConvergenceHistoryTerms);
1694 0 : if (std::abs(tempHistOutletNode(1) - AvgValue) > DataConvergParams::PlantTemperatureOscillationToler) {
1695 0 : FoundOscillationByDuplicate = false;
1696 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1697 0 : if (std::abs(tempHistOutletNode(1) - tempHistOutletNode(StackDepth)) <
1698 : DataConvergParams::PlantTemperatureOscillationToler) {
1699 0 : FoundOscillationByDuplicate = true;
1700 0 : ShowContinueError(
1701 : state,
1702 0 : format("Node named {} shows oscillating temperatures across iterations with a repeated value of {:.5R}",
1703 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut,
1704 0 : tempHistOutletNode(1)));
1705 0 : break;
1706 : }
1707 : }
1708 : }
1709 0 : if (!FoundOscillationByDuplicate) {
1710 :
1711 0 : Real64 tempHistOutletNodeDotProd = std::inner_product(
1712 0 : std::begin(ConvergenceHistoryARR), std::end(ConvergenceHistoryARR), std::begin(tempHistOutletNode), 0.0);
1713 :
1714 0 : SlopeTemps =
1715 0 : (sum_ConvergenceHistoryARR * sum(tempHistOutletNode) -
1716 0 : double(NumConvergenceHistoryTerms) * tempHistOutletNodeDotProd) /
1717 : (square_sum_ConvergenceHistoryARR - double(NumConvergenceHistoryTerms) * sum_square_ConvergenceHistoryARR);
1718 0 : if (std::abs(SlopeTemps) > DataConvergParams::PlantFlowRateSlopeToler) {
1719 0 : if (SlopeTemps < 0.0) { // check for monotonic decrease
1720 0 : MonotonicDecreaseFound = true;
1721 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1722 0 : if (state.dataPlnt->PlantLoop(LoopNum)
1723 0 : .LoopSide(ThisLoopSide)
1724 0 : .OutletNode.TemperatureHistory(StackDepth - 1) > tempHistOutletNode(StackDepth)) {
1725 0 : MonotonicDecreaseFound = false;
1726 0 : break;
1727 : }
1728 : }
1729 0 : if (MonotonicDecreaseFound) {
1730 0 : ShowContinueError(state,
1731 0 : format("Node named {} shows monotonically decreasing temperatures with a trend "
1732 : "rate across iterations of {:.5R} [C/iteration]",
1733 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut,
1734 0 : SlopeTemps));
1735 : }
1736 : } else { // check for monotonic increase
1737 0 : MonotonicIncreaseFound = true;
1738 0 : for (StackDepth = 2; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1739 0 : if (state.dataPlnt->PlantLoop(LoopNum)
1740 0 : .LoopSide(ThisLoopSide)
1741 0 : .OutletNode.TemperatureHistory(StackDepth - 1) < tempHistOutletNode(StackDepth)) {
1742 0 : MonotonicIncreaseFound = false;
1743 0 : break;
1744 : }
1745 : }
1746 0 : if (MonotonicIncreaseFound) {
1747 0 : ShowContinueError(state,
1748 0 : format("Node named {} shows monotonically increasing temperatures with a trend "
1749 : "rate across iterations of {:.5R} [C/iteration]",
1750 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut,
1751 0 : SlopeTemps));
1752 : }
1753 : }
1754 : } // significant slope found
1755 : } // no oscillation found
1756 :
1757 0 : if (MonotonicDecreaseFound || MonotonicIncreaseFound || FoundOscillationByDuplicate) {
1758 0 : HistoryTrace = "";
1759 0 : for (StackDepth = 1; StackDepth <= NumConvergenceHistoryTerms; ++StackDepth) {
1760 0 : HistoryTrace += format("{:.5R},", tempHistOutletNode(StackDepth));
1761 : }
1762 0 : ShowContinueError(state,
1763 0 : "Node named " + state.dataPlnt->PlantLoop(LoopNum).LoopSide(ThisLoopSide).NodeNameOut +
1764 0 : " temperature [C] iteration history trace (most recent first): " + HistoryTrace);
1765 : } // need to report trace
1766 : // end of Outlet node
1767 :
1768 : } // plant loop sides
1769 :
1770 : } // temperature not converged
1771 : } // loop over plant loop systems
1772 : }
1773 : } else {
1774 180 : if (state.dataEnvrn->EnvironmentName == ErrEnvironmentName) {
1775 540 : ShowRecurringWarningErrorAtEnd(state,
1776 360 : "SimHVAC: Exceeding Maximum iterations for all HVAC loops, during " +
1777 540 : state.dataEnvrn->EnvironmentName + " continues",
1778 : MaxErrCount);
1779 : } else {
1780 0 : MaxErrCount = 0;
1781 0 : ErrEnvironmentName = state.dataEnvrn->EnvironmentName;
1782 0 : ShowRecurringWarningErrorAtEnd(state,
1783 0 : "SimHVAC: Exceeding Maximum iterations for all HVAC loops, during " +
1784 0 : state.dataEnvrn->EnvironmentName + " continues",
1785 : MaxErrCount);
1786 : }
1787 : }
1788 : }
1789 :
1790 2638872 : CheckAirLoopFlowBalance(state);
1791 :
1792 : // Set node setpoints to a flag value so that controllers can check whether their sensed nodes
1793 : // have a setpoint
1794 2638872 : if (!state.dataGlobal->ZoneSizingCalc && !state.dataGlobal->SysSizingCalc) {
1795 2638872 : if (state.dataHVACMgr->MySetPointInit) {
1796 769 : if (state.dataLoopNodes->NumOfNodes > 0) {
1797 60129 : for (auto &e : state.dataLoopNodes->Node) {
1798 59425 : e.TempSetPoint = SensedNodeFlagValue;
1799 59425 : e.HumRatSetPoint = SensedNodeFlagValue;
1800 59425 : e.HumRatMin = SensedNodeFlagValue;
1801 59425 : e.HumRatMax = SensedNodeFlagValue;
1802 59425 : e.MassFlowRateSetPoint = SensedNodeFlagValue; // BG 5-26-2009 (being checked in HVACControllers.cc)
1803 : }
1804 704 : state.dataLoopNodes->DefaultNodeValues.TempSetPoint = SensedNodeFlagValue;
1805 704 : state.dataLoopNodes->DefaultNodeValues.HumRatSetPoint = SensedNodeFlagValue;
1806 704 : state.dataLoopNodes->DefaultNodeValues.HumRatMin = SensedNodeFlagValue;
1807 704 : state.dataLoopNodes->DefaultNodeValues.HumRatMax = SensedNodeFlagValue;
1808 704 : state.dataLoopNodes->DefaultNodeValues.MassFlowRateSetPoint =
1809 : SensedNodeFlagValue; // BG 5-26-2009 (being checked in HVACControllers.cc)
1810 : }
1811 769 : state.dataHVACMgr->MySetPointInit = false;
1812 769 : DoSetPointTest = true;
1813 : } else {
1814 2638103 : DoSetPointTest = false;
1815 : }
1816 :
1817 2638872 : if (state.dataCoilCooingDX->stillNeedToReportStandardRatings) {
1818 947186 : if (!state.dataGlobal->ZoneSizingCalc && !state.dataGlobal->SysSizingCalc && !state.dataGlobal->WarmupFlag) {
1819 769 : CoilCoolingDX::reportAllStandardRatings(state);
1820 : }
1821 : }
1822 : }
1823 2638872 : if (SetPointErrorFlag) {
1824 0 : ShowFatalError(state, "Previous severe set point errors cause program termination");
1825 : }
1826 : }
1827 :
1828 5623121 : void SimSelectedEquipment(EnergyPlusData &state,
1829 : bool &SimAirLoops, // True when the air loops need to be (re)simulated
1830 : bool &SimZoneEquipment, // True when zone equipment components need to be (re)simulated
1831 : bool &SimNonZoneEquipment, // True when non-zone equipment components need to be (re)simulated
1832 : bool &SimPlantLoops, // True when the main plant loops need to be (re)simulated
1833 : bool &SimElecCircuits, // True when electric circuits need to be (re)simulated
1834 : bool &FirstHVACIteration, // True when solution technique on first iteration
1835 : bool const LockPlantFlows)
1836 : {
1837 :
1838 : // SUBROUTINE INFORMATION:
1839 : // AUTHOR Russ Taylor, Rick Strand
1840 : // DATE WRITTEN May 1998
1841 : // MODIFIED na
1842 : // RE-ENGINEERED na
1843 :
1844 : // PURPOSE OF THIS SUBROUTINE:
1845 : // This subroutine receives the flags from SimHVAC which determines
1846 : // which middle-level managers must be called.
1847 :
1848 : // METHODOLOGY EMPLOYED:
1849 : // Each flag is checked and the appropriate manager is then called.
1850 :
1851 : // Using/Aliasing
1852 : using NonZoneEquipmentManager::ManageNonZoneEquipment;
1853 : using PlantManager::ManagePlantLoops;
1854 : using PlantUtilities::AnyPlantLoopSidesNeedSim;
1855 : using PlantUtilities::ResetAllPlantInterConnectFlags;
1856 : using PlantUtilities::SetAllFlowLocks;
1857 : using SimAirServingZones::ManageAirLoops;
1858 : using ZoneEquipmentManager::ManageZoneEquipment;
1859 :
1860 : // Locals
1861 : // SUBROUTINE ARGUMENT DEFINITIONS:
1862 : bool ResimulateAirZone; // True when solution technique on third iteration used in AirflowNetwork
1863 :
1864 : // SUBROUTINE PARAMETER DEFINITIONS:
1865 5623121 : int constexpr MaxAir(5); // Iteration Max for Air Simulation Iterations
1866 :
1867 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1868 : int IterAir; // counts iterations to enforce maximum iteration limit
1869 :
1870 5623121 : IterAir = 0;
1871 :
1872 : // Set all plant flow locks to UNLOCKED to allow air side components to operate properly
1873 : // This requires that the plant flow resolver carefully set the min/max avail limits on
1874 : // air side components to ensure they request within bounds.
1875 5623121 : if (LockPlantFlows) {
1876 14764 : SetAllFlowLocks(state, DataPlant::FlowLock::Locked);
1877 : } else {
1878 5608357 : SetAllFlowLocks(state, DataPlant::FlowLock::Unlocked);
1879 : }
1880 5623121 : ResetAllPlantInterConnectFlags(state);
1881 :
1882 5623121 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHVACMgr->MyEnvrnFlag2) {
1883 : // Following comment is incorrect! (LKL) Even the first time through this does more than read in data.
1884 : // Zone equipment data needs to be read in before air loop data to allow the
1885 : // determination of which zones are connected to which air loops.
1886 : // This call of ManageZoneEquipment does nothing except force the
1887 : // zone equipment data to be read in.
1888 4495 : ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipment, SimAirLoops);
1889 4495 : state.dataHVACMgr->MyEnvrnFlag2 = false;
1890 : }
1891 5623121 : if (!state.dataGlobal->BeginEnvrnFlag) {
1892 5596759 : state.dataHVACMgr->MyEnvrnFlag2 = true;
1893 : }
1894 :
1895 5623121 : if (FirstHVACIteration) {
1896 2638872 : state.dataHVACMgr->RepIterAir = 0;
1897 : // Call AirflowNetwork simulation to calculate air flows and pressures
1898 2638872 : if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
1899 136813 : state.afn->manage_balance(FirstHVACIteration);
1900 : }
1901 2638872 : ManageAirLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment);
1902 2638872 : state.dataAirLoop->AirLoopInputsFilled = true; // all air loop inputs have been read in
1903 2638872 : SimAirLoops = true; // Need to make sure that SimAirLoop is simulated at min twice to calculate PLR in some air loop equipment
1904 2638872 : state.dataHVACGlobal->AirLoopsSimOnce = true; // air loops simulated once for this environment
1905 2638872 : ResetTerminalUnitFlowLimits(state);
1906 2638872 : state.dataHVACMgr->FlowMaxAvailAlreadyReset = true;
1907 2638872 : ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipment, SimAirLoops);
1908 2638872 : SimZoneEquipment = true; // needs to be simulated at least twice for flow resolution to propagate to this routine
1909 2638872 : ManageNonZoneEquipment(state, FirstHVACIteration, SimNonZoneEquipment);
1910 7916616 : state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
1911 5277744 : state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
1912 :
1913 2638872 : ManagePlantLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment, SimNonZoneEquipment, SimPlantLoops, SimElecCircuits);
1914 :
1915 2638872 : state.dataErrTracking->AskForPlantCheckOnAbort = true; // need to make a first pass through plant calcs before this check make sense
1916 7916616 : state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
1917 5277744 : state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
1918 : } else {
1919 2984249 : state.dataHVACMgr->FlowResolutionNeeded = false;
1920 10676547 : while ((SimAirLoops || SimZoneEquipment) && (IterAir <= MaxAir)) {
1921 3846149 : ++IterAir; // Increment the iteration counter
1922 : // Call AirflowNetwork simulation to calculate air flows and pressures
1923 3846149 : ResimulateAirZone = false;
1924 3846149 : if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
1925 357307 : state.afn->manage_balance(FirstHVACIteration, IterAir, ResimulateAirZone);
1926 : }
1927 3846149 : if (SimAirLoops) {
1928 3845724 : ManageAirLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment);
1929 3845724 : SimElecCircuits = true; // If this was simulated there are possible electric changes that need to be simulated
1930 : }
1931 :
1932 : // make sure flow resolution gets done
1933 3846149 : if (state.dataHVACMgr->FlowResolutionNeeded) {
1934 103080 : SimZoneEquipment = true;
1935 : }
1936 3846149 : if (SimZoneEquipment) {
1937 3406461 : if ((IterAir == 1) && (!state.dataHVACMgr->FlowMaxAvailAlreadyReset)) { // don't do reset if already done in FirstHVACIteration
1938 : // ResetTerminalUnitFlowLimits(); // don't do reset at all - interferes with convergence and terminal unit flow controls
1939 150583 : state.dataHVACMgr->FlowResolutionNeeded = true;
1940 : } else {
1941 3255878 : ResolveAirLoopFlowLimits(state);
1942 3255878 : state.dataHVACMgr->FlowResolutionNeeded = false;
1943 : }
1944 3406461 : ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipment, SimAirLoops);
1945 3406461 : SimElecCircuits = true; // If this was simulated there are possible electric changes that need to be simulated
1946 : }
1947 3846149 : state.dataHVACMgr->FlowMaxAvailAlreadyReset = false;
1948 :
1949 : // IterAir = IterAir + 1 ! Increment the iteration counter
1950 3846149 : if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
1951 357307 : if (ResimulateAirZone) { // Need to make sure that SimAirLoop and SimZoneEquipment are simulated
1952 166412 : SimAirLoops = true; // at min three times using ONOFF fan with the AirflowNetwork model
1953 166412 : SimZoneEquipment = true;
1954 : }
1955 : }
1956 : }
1957 :
1958 2984249 : state.dataHVACMgr->RepIterAir += IterAir;
1959 : // Check to see if any components have been locked out. If so, SimAirLoops will be reset to TRUE.
1960 2984249 : ResolveLockoutFlags(state, SimAirLoops);
1961 :
1962 2984249 : if (SimNonZoneEquipment) {
1963 2653636 : ManageNonZoneEquipment(state, FirstHVACIteration, SimNonZoneEquipment);
1964 2653636 : SimElecCircuits = true; // If this was simulated there are possible electric changes that need to be simulated
1965 : }
1966 :
1967 2984249 : if (SimElecCircuits) {
1968 8907000 : state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
1969 5938000 : state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
1970 : }
1971 :
1972 2984249 : if (!SimPlantLoops) {
1973 : // check to see if any air side component may have requested plant resim
1974 330128 : if (AnyPlantLoopSidesNeedSim(state)) {
1975 45758 : SimPlantLoops = true;
1976 : }
1977 : }
1978 :
1979 2984249 : if (SimPlantLoops) {
1980 2699879 : ManagePlantLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment, SimNonZoneEquipment, SimPlantLoops, SimElecCircuits);
1981 : }
1982 :
1983 2984249 : if (SimElecCircuits) {
1984 4824 : state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
1985 3216 : state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
1986 : }
1987 : }
1988 5623121 : }
1989 :
1990 2638872 : void ResetTerminalUnitFlowLimits(EnergyPlusData &state)
1991 : {
1992 :
1993 : // SUBROUTINE INFORMATION:
1994 : // AUTHOR Fred Buhl
1995 : // DATE WRITTEN Feb 2010
1996 : // MODIFIED na
1997 : // RE-ENGINEERED na
1998 :
1999 : // PURPOSE OF THIS SUBROUTINE:
2000 : // Reset the max flow available limits at the inlet nodes of terminal units
2001 :
2002 : // METHODOLOGY EMPLOYED:
2003 : // Loops through all air loops, finds the inlet nodes of the terminal units
2004 : // served by each air loop, and resets the node MassFlowRateMaxAvail (and MinAvail) to
2005 : // the hard max and mins.
2006 :
2007 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2008 : int AirLoopIndex;
2009 : int ZonesCooledIndex;
2010 : int ZonesHeatedIndex;
2011 : int TermInletNode;
2012 :
2013 6860298 : for (AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the primary air loops
2014 17273386 : for (ZonesCooledIndex = 1; ZonesCooledIndex <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex).NumZonesCooled;
2015 : ++ZonesCooledIndex) { // loop over the zones cooled by this air loop
2016 13051960 : TermInletNode = state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex).TermUnitCoolInletNodes(ZonesCooledIndex);
2017 : // reset the max avail flow rate at the terminal unit cold air inlet to the max
2018 13051960 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
2019 13051960 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMin;
2020 : }
2021 4304665 : for (ZonesHeatedIndex = 1; ZonesHeatedIndex <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex).NumZonesHeated;
2022 : ++ZonesHeatedIndex) { // loop over the zones heated by this air loop
2023 83239 : TermInletNode = state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex).TermUnitHeatInletNodes(ZonesHeatedIndex);
2024 : // reset the max avail flow rate at the terminal unit hot air inlet to the max
2025 83239 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
2026 83239 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMin;
2027 : }
2028 : }
2029 2638872 : }
2030 :
2031 3255878 : void ResolveAirLoopFlowLimits(EnergyPlusData &state)
2032 : {
2033 :
2034 : // SUBROUTINE INFORMATION:
2035 : // AUTHOR Fred Buhl
2036 : // DATE WRITTEN August 2003
2037 : // MODIFIED na
2038 : // RE-ENGINEERED na
2039 :
2040 : // PURPOSE OF THIS SUBROUTINE:
2041 : // This subroutine is for resolving hard flow mismatches between zone equipment and
2042 : // the primary air loop. Such a mismatch can occur when the air terminal units are
2043 : // requesting more air than the central air system can supply.
2044 :
2045 : // METHODOLOGY EMPLOYED:
2046 : // Sets the MassFlowRateMaxAvail on the terminal unit inlet nodes to match the
2047 : // maximum available from the primary air loop.
2048 :
2049 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2050 : int AirLoopIndex;
2051 : int ZonesCooledIndex;
2052 : int ZonesHeatedIndex;
2053 : int TermInletNode;
2054 : int SupplyIndex;
2055 : int SupplyNode;
2056 : Real64 FlowRatio;
2057 :
2058 9393621 : for (AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the primary air loops
2059 :
2060 6137743 : auto &AirToZoneNodeInfo(state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex));
2061 :
2062 12302008 : for (SupplyIndex = 1; SupplyIndex <= AirToZoneNodeInfo.NumSupplyNodes; ++SupplyIndex) { // loop over the air loop supply outlets
2063 6164265 : if (AirToZoneNodeInfo.SupplyDuctType(SupplyIndex) == DataHVACGlobals::AirDuctType::Cooling) { // check for cooling duct
2064 : // check if terminal units requesting more air than air loop can supply; if so, set terminal unit inlet
2065 : // node mass flow max avail to what air loop can supply
2066 5856059 : SupplyNode = AirToZoneNodeInfo.AirLoopSupplyNodeNum(SupplyIndex);
2067 5856059 : if (state.dataLoopNodes->Node(SupplyNode).MassFlowRate > 0.0) {
2068 : // must include bypass flow for ChangeoverBypass system so that terminal units are not restricted (e.g., MaxAvail is lowered)
2069 14637171 : if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
2070 9758114 : state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) > DataConvergParams::HVACFlowRateToler * 0.01) {
2071 599179 : FlowRatio = state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
2072 1364704 : for (ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
2073 765525 : TermInletNode = AirToZoneNodeInfo.TermUnitCoolInletNodes(ZonesCooledIndex);
2074 765525 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
2075 765525 : state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
2076 765525 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
2077 765525 : min(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
2078 765525 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
2079 : }
2080 : }
2081 14637171 : if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
2082 9758114 : state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) < -DataConvergParams::HVACFlowRateToler * 0.01) {
2083 219194 : if (state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint == 0.0) {
2084 : // CALL ShowFatalError('ResolveAirLoopFlowLimits: Node MassFlowRateSetPoint = 0.0, Node='// &
2085 : // TRIM(state.dataLoopNodes->NodeID(SupplyNode))// &
2086 : // ', check for Node Connection Errors in the following messages.')
2087 36 : for (ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
2088 18 : TermInletNode = AirToZoneNodeInfo.TermUnitCoolInletNodes(ZonesCooledIndex);
2089 18 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
2090 18 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
2091 18 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
2092 18 : state.dataLoopNodes->Node(SupplyNode).MassFlowRate / double(AirToZoneNodeInfo.NumZonesCooled);
2093 : }
2094 : } else {
2095 219176 : FlowRatio =
2096 219176 : state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
2097 453544 : for (ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
2098 234368 : TermInletNode = AirToZoneNodeInfo.TermUnitCoolInletNodes(ZonesCooledIndex);
2099 234368 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
2100 234368 : state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
2101 234368 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
2102 234368 : max(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
2103 234368 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
2104 : }
2105 : }
2106 : }
2107 : }
2108 : }
2109 : }
2110 12302008 : for (SupplyIndex = 1; SupplyIndex <= AirToZoneNodeInfo.NumSupplyNodes; ++SupplyIndex) { // loop over the air loop supply outlets
2111 6164265 : if (AirToZoneNodeInfo.SupplyDuctType(SupplyIndex) == DataHVACGlobals::AirDuctType::Heating) { // check for heating duct
2112 : // check if terminal units requesting more air than air loop can supply; if so, set terminal unit inlet
2113 : // node mass flow max avail to what air loop can supply
2114 26522 : SupplyNode = AirToZoneNodeInfo.AirLoopSupplyNodeNum(SupplyIndex);
2115 26522 : if (state.dataLoopNodes->Node(SupplyNode).MassFlowRate > 0.0) {
2116 : // must include bypass flow for ChangeoverBypass system so that terminal units are not restricted (e.g., MaxAvail is lowered)
2117 62016 : if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
2118 41344 : state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) > DataConvergParams::HVACFlowRateToler * 0.01) {
2119 0 : FlowRatio = state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
2120 0 : for (ZonesHeatedIndex = 1; ZonesHeatedIndex <= AirToZoneNodeInfo.NumZonesHeated; ++ZonesHeatedIndex) {
2121 0 : TermInletNode = AirToZoneNodeInfo.TermUnitHeatInletNodes(ZonesHeatedIndex);
2122 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
2123 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
2124 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
2125 0 : min(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
2126 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
2127 : }
2128 : }
2129 62016 : if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
2130 41344 : state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) < -DataConvergParams::HVACFlowRateToler * 0.01) {
2131 2 : if (state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint == 0.0) {
2132 : // ', check for Node Connection Errors in the following messages.')
2133 0 : for (ZonesHeatedIndex = 1; ZonesHeatedIndex <= AirToZoneNodeInfo.NumZonesHeated; ++ZonesHeatedIndex) {
2134 0 : TermInletNode = AirToZoneNodeInfo.TermUnitHeatInletNodes(ZonesHeatedIndex);
2135 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
2136 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
2137 0 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
2138 0 : state.dataLoopNodes->Node(SupplyNode).MassFlowRate / double(AirToZoneNodeInfo.NumZonesCooled);
2139 : }
2140 : } else {
2141 2 : FlowRatio =
2142 2 : state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
2143 14 : for (ZonesHeatedIndex = 1; ZonesHeatedIndex <= AirToZoneNodeInfo.NumZonesHeated; ++ZonesHeatedIndex) {
2144 12 : TermInletNode = AirToZoneNodeInfo.TermUnitHeatInletNodes(ZonesHeatedIndex);
2145 12 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
2146 12 : state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
2147 12 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
2148 12 : max(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
2149 12 : state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
2150 : }
2151 : }
2152 : }
2153 : }
2154 : }
2155 : }
2156 : }
2157 3255878 : }
2158 :
2159 2984249 : void ResolveLockoutFlags(EnergyPlusData &state, bool &SimAir) // TRUE means air loops must be (re)simulated
2160 : {
2161 :
2162 : // SUBROUTINE INFORMATION:
2163 : // AUTHOR Fred Buhl
2164 : // DATE WRITTEN December 2003
2165 : // MODIFIED na
2166 : // RE-ENGINEERED na
2167 :
2168 : // PURPOSE OF THIS SUBROUTINE:
2169 : // This subroutine checks for components lockout flags and asks for air loop resimulation
2170 : // if any components have been locked out
2171 :
2172 : // METHODOLOGY EMPLOYED:
2173 : // Checks if loop lockout flags are .TRUE.; if so, sets SimAirLoops to .TRUE.
2174 :
2175 2984249 : auto &AirLoopControlInfo(state.dataAirLoop->AirLoopControlInfo);
2176 :
2177 8377596 : for (int AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the primary air loops
2178 : // check if economizer ia active and if there is a request that it be locked out
2179 6276956 : if (AirLoopControlInfo(AirLoopIndex).EconoActive &&
2180 1639884 : (AirLoopControlInfo(AirLoopIndex).ReqstEconoLockoutWithCompressor || AirLoopControlInfo(AirLoopIndex).ReqstEconoLockoutWithHeating)) {
2181 52367 : AirLoopControlInfo(AirLoopIndex).EconoLockout = true;
2182 52367 : SimAir = true;
2183 : }
2184 : }
2185 2984249 : }
2186 :
2187 2638872 : void ResetHVACControl(EnergyPlusData &state)
2188 : {
2189 :
2190 : // SUBROUTINE INFORMATION:
2191 : // AUTHOR Fred Buhl
2192 : // DATE WRITTEN December 2004
2193 : // MODIFIED na
2194 : // RE-ENGINEERED na
2195 :
2196 : // PURPOSE OF THIS SUBROUTINE:
2197 : // This subroutine resets loop control flags and specified flow rates that may
2198 : // have been set by the set point and availability managers in the previous
2199 : // time step
2200 :
2201 2638872 : if (state.dataHVACGlobal->NumPrimaryAirSys == 0) return;
2202 6101943 : for (auto &e : state.dataAirLoop->AirLoopControlInfo) {
2203 4221179 : e.NightVent = false;
2204 4221179 : e.LoopFlowRateSet = false;
2205 : }
2206 6101943 : for (auto &e : state.dataAirLoop->AirLoopFlow)
2207 4221179 : e.ReqSupplyFrac = 1.0;
2208 : }
2209 :
2210 1613 : void ResetNodeData(EnergyPlusData &state)
2211 : {
2212 :
2213 : // SUBROUTINE INFORMATION:
2214 : // AUTHOR Linda Lawrie
2215 : // DATE WRITTEN March 2005
2216 : // MODIFIED na
2217 : // RE-ENGINEERED na
2218 :
2219 : // PURPOSE OF THIS SUBROUTINE:
2220 : // This routine resets all node data to "initial" conditions.
2221 :
2222 1613 : if (state.dataLoopNodes->NumOfNodes <= 0) return;
2223 :
2224 125701 : for (auto &e : state.dataLoopNodes->Node) {
2225 124244 : e.Temp = state.dataLoopNodes->DefaultNodeValues.Temp;
2226 124244 : e.TempMin = state.dataLoopNodes->DefaultNodeValues.TempMin;
2227 124244 : e.TempMax = state.dataLoopNodes->DefaultNodeValues.TempMax;
2228 124244 : e.TempSetPoint = state.dataLoopNodes->DefaultNodeValues.TempSetPoint;
2229 124244 : e.MassFlowRate = state.dataLoopNodes->DefaultNodeValues.MassFlowRate;
2230 124244 : e.MassFlowRateMin = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMin;
2231 124244 : e.MassFlowRateMax = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMax;
2232 124244 : e.MassFlowRateMinAvail = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMinAvail;
2233 124244 : e.MassFlowRateMaxAvail = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMaxAvail;
2234 124244 : e.MassFlowRateSetPoint = state.dataLoopNodes->DefaultNodeValues.MassFlowRateSetPoint;
2235 124244 : e.Quality = state.dataLoopNodes->DefaultNodeValues.Quality;
2236 124244 : e.Press = state.dataLoopNodes->DefaultNodeValues.Press;
2237 124244 : e.Enthalpy = state.dataLoopNodes->DefaultNodeValues.Enthalpy;
2238 124244 : e.HumRat = state.dataLoopNodes->DefaultNodeValues.HumRat;
2239 124244 : e.HumRatMin = state.dataLoopNodes->DefaultNodeValues.HumRatMin;
2240 124244 : e.HumRatMax = state.dataLoopNodes->DefaultNodeValues.HumRatMax;
2241 124244 : e.HumRatSetPoint = state.dataLoopNodes->DefaultNodeValues.HumRatSetPoint;
2242 124244 : e.TempSetPointHi = state.dataLoopNodes->DefaultNodeValues.TempSetPointHi;
2243 124244 : e.TempSetPointLo = state.dataLoopNodes->DefaultNodeValues.TempSetPointLo;
2244 : }
2245 :
2246 1457 : if (allocated(state.dataLoopNodes->MoreNodeInfo)) {
2247 125701 : for (auto &e : state.dataLoopNodes->MoreNodeInfo) {
2248 124244 : e.WetBulbTemp = state.dataLoopNodes->DefaultNodeValues.Temp;
2249 124244 : e.RelHumidity = 0.0;
2250 124244 : e.ReportEnthalpy = state.dataLoopNodes->DefaultNodeValues.Enthalpy;
2251 124244 : e.VolFlowRateStdRho = 0.0;
2252 124244 : e.VolFlowRateCrntRho = 0.0;
2253 124244 : e.Density = 0.0;
2254 : }
2255 : }
2256 : }
2257 :
2258 3318787 : void UpdateZoneListAndGroupLoads(EnergyPlusData &state)
2259 : {
2260 :
2261 : // SUBROUTINE INFORMATION:
2262 : // AUTHOR Apparently someone who doesn't believe in documenting.
2263 : // DATE WRITTEN ???
2264 : // MODIFIED na
2265 : // RE-ENGINEERED na
2266 :
2267 : // Using/Aliasing
2268 : using namespace DataHeatBalance;
2269 :
2270 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2271 : int ZoneNum;
2272 : int ListNum;
2273 : int GroupNum;
2274 : int Mult;
2275 :
2276 3318787 : auto &ZoneList(state.dataHeatBal->ZoneList);
2277 3318787 : auto &ZoneGroup(state.dataHeatBal->ZoneGroup);
2278 3318787 : auto &ZoneListSNLoadHeatEnergy(state.dataHeatBal->ZoneListSNLoadHeatEnergy);
2279 3318787 : auto &ZoneListSNLoadCoolEnergy(state.dataHeatBal->ZoneListSNLoadCoolEnergy);
2280 3318787 : auto &ZoneListSNLoadHeatRate(state.dataHeatBal->ZoneListSNLoadHeatRate);
2281 3318787 : auto &ZoneListSNLoadCoolRate(state.dataHeatBal->ZoneListSNLoadCoolRate);
2282 :
2283 : // Sum ZONE LIST and ZONE GROUP report variables
2284 3458626 : for (ListNum = 1; ListNum <= state.dataHeatBal->NumOfZoneLists; ++ListNum) {
2285 139839 : ZoneListSNLoadHeatEnergy(ListNum) = 0.0;
2286 139839 : ZoneListSNLoadCoolEnergy(ListNum) = 0.0;
2287 139839 : ZoneListSNLoadHeatRate(ListNum) = 0.0;
2288 139839 : ZoneListSNLoadCoolRate(ListNum) = 0.0;
2289 : }
2290 :
2291 3458626 : for (ListNum = 1; ListNum <= state.dataHeatBal->NumOfZoneLists; ++ListNum) {
2292 707485 : for (ZoneNum = 1; ZoneNum <= ZoneList(ListNum).NumOfZones; ++ZoneNum) {
2293 567646 : Mult = state.dataHeatBal->Zone(ZoneNum).Multiplier;
2294 567646 : ZoneListSNLoadHeatEnergy(ListNum) +=
2295 567646 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneList(ListNum).Zone(ZoneNum)).ZoneSNLoadHeatEnergy * Mult;
2296 567646 : ZoneListSNLoadCoolEnergy(ListNum) +=
2297 567646 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneList(ListNum).Zone(ZoneNum)).ZoneSNLoadCoolEnergy * Mult;
2298 567646 : ZoneListSNLoadHeatRate(ListNum) +=
2299 567646 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneList(ListNum).Zone(ZoneNum)).ZoneSNLoadHeatRate * Mult;
2300 567646 : ZoneListSNLoadCoolRate(ListNum) +=
2301 567646 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneList(ListNum).Zone(ZoneNum)).ZoneSNLoadCoolRate * Mult;
2302 : } // ZoneNum
2303 : } // ListNum
2304 :
2305 3346117 : for (GroupNum = 1; GroupNum <= state.dataHeatBal->NumOfZoneGroups; ++GroupNum) {
2306 27330 : Mult = state.dataHeatBal->ZoneGroup(GroupNum).Multiplier;
2307 27330 : state.dataHeatBal->ZoneGroupSNLoadHeatEnergy(GroupNum) = ZoneListSNLoadHeatEnergy(ZoneGroup(GroupNum).ZoneList) * Mult;
2308 27330 : state.dataHeatBal->ZoneGroupSNLoadCoolEnergy(GroupNum) = ZoneListSNLoadCoolEnergy(ZoneGroup(GroupNum).ZoneList) * Mult;
2309 27330 : state.dataHeatBal->ZoneGroupSNLoadHeatRate(GroupNum) = ZoneListSNLoadHeatRate(ZoneGroup(GroupNum).ZoneList) * Mult;
2310 27330 : state.dataHeatBal->ZoneGroupSNLoadCoolRate(GroupNum) = ZoneListSNLoadCoolRate(ZoneGroup(GroupNum).ZoneList) * Mult;
2311 : } // GroupNum
2312 3318787 : }
2313 :
2314 389283 : void ReportInfiltrations(EnergyPlusData &state)
2315 : {
2316 : // SUBROUTINE INFORMATION:
2317 : // AUTHOR Yueyue Zhou
2318 : // DATE WRITTEN July 2021
2319 :
2320 : // PURPOSE OF THIS SUBROUTINE:
2321 : // This subroutine currently creates the values for standard Infiltration object level reporting
2322 :
2323 : // METHODOLOGY EMPLOYED:
2324 :
2325 : // REFERENCES:
2326 :
2327 : using DataHVACGlobals::CycleOn;
2328 : using DataHVACGlobals::CycleOnZoneFansOnly;
2329 : using Psychrometrics::PsyCpAirFnW;
2330 : using Psychrometrics::PsyHgAirFnWTdb;
2331 : using Psychrometrics::PsyRhoAirFnPbTdbW;
2332 : // SUBROUTINE PARAMETER DEFINITIONS:
2333 389283 : static std::string const RoutineName("ReportInfiltrations");
2334 :
2335 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2336 : Real64 AirDensity; // Density of air (kg/m^3)
2337 : Real64 CpAir; // Heat capacity of air (J/kg-C)
2338 : Real64 TotalLoad; // Total loss or gain
2339 : Real64 H2OHtOfVap; // Heat of vaporization of air
2340 : Real64 ADSCorrectionFactor; // Correction factor of air flow model values when ADS is simulated
2341 389283 : Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
2342 :
2343 2317345 : for (auto &thisInfiltration : state.dataHeatBal->Infiltration) {
2344 :
2345 1928062 : int NZ = thisInfiltration.ZonePtr;
2346 1928062 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(NZ);
2347 1928062 : auto &thisZone = state.dataHeatBal->Zone(NZ);
2348 1928062 : ADSCorrectionFactor = 1.0;
2349 1928062 : if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
2350 : // CR7608 IF (TurnFansOn .AND. AirflowNetworkZoneFlag(NZ)) ADSCorrectionFactor=0
2351 3830 : if ((state.dataZoneEquip->ZoneEquipAvail(NZ) == CycleOn || state.dataZoneEquip->ZoneEquipAvail(NZ) == CycleOnZoneFansOnly) &&
2352 1134 : state.afn->AirflowNetworkZoneFlag(NZ))
2353 1134 : ADSCorrectionFactor = 0.0;
2354 : }
2355 :
2356 1928062 : CpAir = PsyCpAirFnW(state.dataEnvrn->OutHumRat);
2357 1928062 : thisInfiltration.InfilMdot = thisInfiltration.MCpI_temp / CpAir * ADSCorrectionFactor;
2358 1928062 : thisInfiltration.InfilMass = thisInfiltration.InfilMdot * TimeStepSys * DataGlobalConstants::SecInHour;
2359 :
2360 1928062 : if (thisZoneHB.MAT > thisZone.OutDryBulbTemp) {
2361 :
2362 2775916 : thisInfiltration.InfilHeatLoss = thisInfiltration.MCpI_temp * (thisZoneHB.MAT - thisZone.OutDryBulbTemp) * TimeStepSys *
2363 1387958 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2364 1387958 : thisInfiltration.InfilHeatGain = 0.0;
2365 :
2366 540104 : } else if (thisZoneHB.MAT <= thisZone.OutDryBulbTemp) {
2367 :
2368 1080208 : thisInfiltration.InfilHeatGain = thisInfiltration.MCpI_temp * (thisZone.OutDryBulbTemp - thisZoneHB.MAT) * TimeStepSys *
2369 540104 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2370 540104 : thisInfiltration.InfilHeatLoss = 0.0;
2371 : }
2372 :
2373 : // Report infiltration latent gains and losses
2374 1928062 : H2OHtOfVap = PsyHgAirFnWTdb(thisZoneHB.ZoneAirHumRat, thisZoneHB.MAT);
2375 1928062 : if (thisZoneHB.ZoneAirHumRat > state.dataEnvrn->OutHumRat) {
2376 :
2377 2005234 : thisInfiltration.InfilLatentLoss = thisInfiltration.InfilMdot * (thisZoneHB.ZoneAirHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap *
2378 1002617 : TimeStepSys * DataGlobalConstants::SecInHour;
2379 1002617 : thisInfiltration.InfilLatentGain = 0.0;
2380 :
2381 925445 : } else if (thisZoneHB.ZoneAirHumRat <= state.dataEnvrn->OutHumRat) {
2382 :
2383 1850890 : thisInfiltration.InfilLatentGain = thisInfiltration.InfilMdot * (state.dataEnvrn->OutHumRat - thisZoneHB.ZoneAirHumRat) * H2OHtOfVap *
2384 925445 : TimeStepSys * DataGlobalConstants::SecInHour;
2385 925445 : thisInfiltration.InfilLatentLoss = 0.0;
2386 : }
2387 : // Total infiltration losses and gains
2388 1928062 : TotalLoad =
2389 1928062 : thisInfiltration.InfilHeatGain + thisInfiltration.InfilLatentGain - thisInfiltration.InfilHeatLoss - thisInfiltration.InfilLatentLoss;
2390 1928062 : if (TotalLoad > 0) {
2391 490950 : thisInfiltration.InfilTotalGain = TotalLoad;
2392 490950 : thisInfiltration.InfilTotalLoss = 0.0;
2393 : } else {
2394 1437112 : thisInfiltration.InfilTotalGain = 0.0;
2395 1437112 : thisInfiltration.InfilTotalLoss = -TotalLoad;
2396 : }
2397 : // CR7751 second, calculate using indoor conditions for density property
2398 1928062 : AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRatAvg, RoutineName);
2399 1928062 : thisInfiltration.InfilVdotCurDensity = thisInfiltration.InfilMdot / AirDensity;
2400 1928062 : thisInfiltration.InfilVolumeCurDensity = thisInfiltration.InfilVdotCurDensity * TimeStepSys * DataGlobalConstants::SecInHour;
2401 1928062 : thisInfiltration.InfilAirChangeRate = thisInfiltration.InfilVolumeCurDensity / (TimeStepSys * thisZone.Volume);
2402 :
2403 : // CR7751 third, calculate using standard dry air at nominal elevation
2404 1928062 : AirDensity = state.dataEnvrn->StdRhoAir;
2405 1928062 : thisInfiltration.InfilVdotStdDensity = thisInfiltration.InfilMdot / AirDensity;
2406 1928062 : thisInfiltration.InfilVolumeStdDensity = thisInfiltration.InfilVdotStdDensity * TimeStepSys * DataGlobalConstants::SecInHour;
2407 : }
2408 389283 : }
2409 :
2410 401522 : void ReportAirHeatBalance(EnergyPlusData &state)
2411 : {
2412 :
2413 : // SUBROUTINE INFORMATION:
2414 : // AUTHOR Linda Lawrie
2415 : // DATE WRITTEN July 2000
2416 : // MODIFIED Shirey, Jan 2008 (MIXING/CROSS MIXING outputs)
2417 :
2418 : // PURPOSE OF THIS SUBROUTINE:
2419 : // This subroutine updates the report variables for the AirHeatBalance.
2420 :
2421 : // Using/Aliasing
2422 : using DataHVACGlobals::CycleOn;
2423 : using DataHVACGlobals::CycleOnZoneFansOnly;
2424 : using DataHVACGlobals::FanType_ZoneExhaust;
2425 : using Psychrometrics::PsyCpAirFnW;
2426 : using Psychrometrics::PsyHgAirFnWTdb;
2427 : using Psychrometrics::PsyRhoAirFnPbTdbW;
2428 :
2429 : static constexpr std::string_view RoutineName3("ReportAirHeatBalance:3");
2430 :
2431 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2432 : Real64 AirDensity; // Density of air (kg/m^3)
2433 : Real64 CpAir; // Heat capacity of air (J/kg-C)
2434 : Real64 ADSCorrectionFactor; // Correction factor of air flow model values when ADS is simulated
2435 : Real64 H2OHtOfVap; // Heat of vaporization of air
2436 : Real64 TotalLoad; // Total loss or gain
2437 401522 : auto &MixSenLoad = state.dataHVACMgr->MixSenLoad; // Mixing sensible loss or gain
2438 401522 : auto &MixLatLoad = state.dataHVACMgr->MixLatLoad; // Mixing latent loss or gain
2439 :
2440 401522 : state.dataHeatBal->ZoneTotalExfiltrationHeatLoss = 0.0;
2441 401522 : state.dataHeatBal->ZoneTotalExhaustHeatLoss = 0.0;
2442 :
2443 401522 : auto &Zone(state.dataHeatBal->Zone);
2444 401522 : auto &ZnAirRpt(state.dataHeatBal->ZnAirRpt);
2445 401522 : auto &Ventilation(state.dataHeatBal->Ventilation);
2446 401522 : auto &Mixing(state.dataHeatBal->Mixing);
2447 401522 : auto &CrossMixing(state.dataHeatBal->CrossMixing);
2448 401522 : auto &RefDoorMixing(state.dataHeatBal->RefDoorMixing);
2449 401522 : auto &ZoneEquipConfig(state.dataZoneEquip->ZoneEquipConfig);
2450 401522 : auto &Fan(state.dataFans->Fan);
2451 401522 : auto &TimeStepSys(state.dataHVACGlobal->TimeStepSys);
2452 :
2453 401522 : if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
2454 13012 : state.afn->report();
2455 : }
2456 :
2457 : // Reports zone exhaust loss by exhaust fans
2458 3038160 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) { // Start of zone loads report variable update loop ...
2459 2636638 : CpAir = PsyCpAirFnW(state.dataEnvrn->OutHumRat);
2460 2636638 : H2OHtOfVap = PsyHgAirFnWTdb(state.dataEnvrn->OutHumRat, Zone(ZoneLoop).OutDryBulbTemp);
2461 2636638 : ADSCorrectionFactor = 1.0;
2462 2636638 : if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
2463 3830 : if ((state.dataZoneEquip->ZoneEquipAvail(ZoneLoop) == CycleOn || state.dataZoneEquip->ZoneEquipAvail(ZoneLoop) == CycleOnZoneFansOnly) &&
2464 1134 : state.afn->AirflowNetworkZoneFlag(ZoneLoop)) {
2465 1134 : ADSCorrectionFactor = 0.0;
2466 : }
2467 : }
2468 :
2469 2636638 : ZnAirRpt(ZoneLoop).ExhTotalLoss = 0;
2470 2636638 : ZnAirRpt(ZoneLoop).ExhSensiLoss = 0;
2471 :
2472 23390912 : for (int FanNum = 1; FanNum <= state.dataFans->NumFans; ++FanNum) {
2473 : // Add reportable vars
2474 20754274 : if (Fan(FanNum).FanType_Num == FanType_ZoneExhaust) {
2475 3835011 : for (int ExhNum = 1; ExhNum <= ZoneEquipConfig(ZoneLoop).NumExhaustNodes; ExhNum++) {
2476 453572 : if (Fan(FanNum).InletNodeNum == ZoneEquipConfig(ZoneLoop).ExhaustNode(ExhNum)) {
2477 53959 : ZnAirRpt(ZoneLoop).ExhTotalLoss +=
2478 53959 : Fan(FanNum).OutletAirMassFlowRate * (Fan(FanNum).OutletAirEnthalpy - state.dataEnvrn->OutEnthalpy) * ADSCorrectionFactor;
2479 161877 : ZnAirRpt(ZoneLoop).ExhSensiLoss += Fan(FanNum).OutletAirMassFlowRate * CpAir *
2480 107918 : (Fan(FanNum).OutletAirTemp - Zone(ZoneLoop).OutDryBulbTemp) * ADSCorrectionFactor;
2481 53959 : break;
2482 : }
2483 : }
2484 : }
2485 : }
2486 :
2487 2636638 : ZnAirRpt(ZoneLoop).ExhLatentLoss = ZnAirRpt(ZoneLoop).ExhTotalLoss - ZnAirRpt(ZoneLoop).ExhSensiLoss;
2488 : }
2489 :
2490 : // Report results for SIMPLE option only
2491 414534 : if (!(state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution ||
2492 13012 : state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation)) {
2493 12239 : return;
2494 : }
2495 :
2496 389283 : if (state.dataHVACMgr->ReportAirHeatBalanceFirstTimeFlag) {
2497 737 : MixSenLoad.allocate(state.dataGlobal->NumOfZones);
2498 737 : MixLatLoad.allocate(state.dataGlobal->NumOfZones);
2499 737 : state.dataHVACMgr->ReportAirHeatBalanceFirstTimeFlag = false;
2500 : }
2501 :
2502 389283 : ReportInfiltrations(state);
2503 :
2504 2985033 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) { // Start of zone loads report variable update loop ...
2505 2595750 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop);
2506 :
2507 : // Break the infiltration load into heat gain and loss components
2508 2595750 : ADSCorrectionFactor = 1.0;
2509 :
2510 2595750 : if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
2511 : // CR7608 IF (TurnFansOn .AND. AirflowNetworkZoneFlag(ZoneLoop)) ADSCorrectionFactor=0
2512 3830 : if ((state.dataZoneEquip->ZoneEquipAvail(ZoneLoop) == CycleOn || state.dataZoneEquip->ZoneEquipAvail(ZoneLoop) == CycleOnZoneFansOnly) &&
2513 1134 : state.afn->AirflowNetworkZoneFlag(ZoneLoop))
2514 1134 : ADSCorrectionFactor = 0.0;
2515 : }
2516 :
2517 2595750 : if (thisZoneHB.MAT > Zone(ZoneLoop).OutDryBulbTemp) {
2518 :
2519 3733436 : ZnAirRpt(ZoneLoop).InfilHeatLoss = thisZoneHB.MCPI * (thisZoneHB.MAT - Zone(ZoneLoop).OutDryBulbTemp) * TimeStepSys *
2520 1866718 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2521 1866718 : ZnAirRpt(ZoneLoop).InfilHeatGain = 0.0;
2522 :
2523 729032 : } else if (thisZoneHB.MAT <= Zone(ZoneLoop).OutDryBulbTemp) {
2524 :
2525 1458064 : ZnAirRpt(ZoneLoop).InfilHeatGain = thisZoneHB.MCPI * (Zone(ZoneLoop).OutDryBulbTemp - thisZoneHB.MAT) * TimeStepSys *
2526 729032 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2527 729032 : ZnAirRpt(ZoneLoop).InfilHeatLoss = 0.0;
2528 : }
2529 : // Report infiltration latent gains and losses
2530 2595750 : CpAir = PsyCpAirFnW(state.dataEnvrn->OutHumRat);
2531 2595750 : H2OHtOfVap = PsyHgAirFnWTdb(thisZoneHB.ZoneAirHumRat, thisZoneHB.MAT);
2532 2595750 : if (thisZoneHB.ZoneAirHumRat > state.dataEnvrn->OutHumRat) {
2533 :
2534 3918351 : ZnAirRpt(ZoneLoop).InfilLatentLoss = thisZoneHB.MCPI / CpAir * (thisZoneHB.ZoneAirHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap *
2535 2612234 : TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2536 1306117 : ZnAirRpt(ZoneLoop).InfilLatentGain = 0.0;
2537 :
2538 1289633 : } else if (thisZoneHB.ZoneAirHumRat <= state.dataEnvrn->OutHumRat) {
2539 :
2540 3868899 : ZnAirRpt(ZoneLoop).InfilLatentGain = thisZoneHB.MCPI / CpAir * (state.dataEnvrn->OutHumRat - thisZoneHB.ZoneAirHumRat) * H2OHtOfVap *
2541 2579266 : TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2542 1289633 : ZnAirRpt(ZoneLoop).InfilLatentLoss = 0.0;
2543 : }
2544 : // Total infiltration losses and gains
2545 5191500 : TotalLoad = ZnAirRpt(ZoneLoop).InfilHeatGain + ZnAirRpt(ZoneLoop).InfilLatentGain - ZnAirRpt(ZoneLoop).InfilHeatLoss -
2546 2595750 : ZnAirRpt(ZoneLoop).InfilLatentLoss;
2547 2595750 : if (TotalLoad > 0) {
2548 490419 : ZnAirRpt(ZoneLoop).InfilTotalGain = TotalLoad * ADSCorrectionFactor;
2549 490419 : ZnAirRpt(ZoneLoop).InfilTotalLoss = 0.0;
2550 : } else {
2551 2105331 : ZnAirRpt(ZoneLoop).InfilTotalGain = 0.0;
2552 2105331 : ZnAirRpt(ZoneLoop).InfilTotalLoss = -TotalLoad * ADSCorrectionFactor;
2553 : }
2554 :
2555 : // first calculate mass flows using outside air heat capacity for consistency with input to heat balance
2556 2595750 : ZnAirRpt(ZoneLoop).InfilMdot = (thisZoneHB.MCPI / CpAir) * ADSCorrectionFactor;
2557 2595750 : ZnAirRpt(ZoneLoop).InfilMass = ZnAirRpt(ZoneLoop).InfilMdot * TimeStepSys * DataGlobalConstants::SecInHour;
2558 2595750 : ZnAirRpt(ZoneLoop).VentilMdot = (thisZoneHB.MCPV / CpAir) * ADSCorrectionFactor;
2559 2595750 : ZnAirRpt(ZoneLoop).VentilMass = ZnAirRpt(ZoneLoop).VentilMdot * TimeStepSys * DataGlobalConstants::SecInHour;
2560 :
2561 : // CR7751 second, calculate using indoor conditions for density property
2562 2595750 : AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRatAvg, RoutineName3);
2563 2595750 : ZnAirRpt(ZoneLoop).InfilVdotCurDensity = ZnAirRpt(ZoneLoop).InfilMdot / AirDensity;
2564 2595750 : ZnAirRpt(ZoneLoop).InfilVolumeCurDensity = ZnAirRpt(ZoneLoop).InfilVdotCurDensity * TimeStepSys * DataGlobalConstants::SecInHour;
2565 2595750 : ZnAirRpt(ZoneLoop).InfilAirChangeRate = ZnAirRpt(ZoneLoop).InfilVolumeCurDensity / (TimeStepSys * Zone(ZoneLoop).Volume);
2566 2595750 : ZnAirRpt(ZoneLoop).VentilVdotCurDensity = ZnAirRpt(ZoneLoop).VentilMdot / AirDensity;
2567 2595750 : ZnAirRpt(ZoneLoop).VentilVolumeCurDensity = ZnAirRpt(ZoneLoop).VentilVdotCurDensity * TimeStepSys * DataGlobalConstants::SecInHour;
2568 2595750 : ZnAirRpt(ZoneLoop).VentilAirChangeRate = ZnAirRpt(ZoneLoop).VentilVolumeCurDensity / (TimeStepSys * Zone(ZoneLoop).Volume);
2569 :
2570 : // CR7751 third, calculate using standard dry air at nominal elevation
2571 2595750 : AirDensity = state.dataEnvrn->StdRhoAir;
2572 2595750 : ZnAirRpt(ZoneLoop).InfilVdotStdDensity = ZnAirRpt(ZoneLoop).InfilMdot / AirDensity;
2573 2595750 : ZnAirRpt(ZoneLoop).InfilVolumeStdDensity = ZnAirRpt(ZoneLoop).InfilVdotStdDensity * TimeStepSys * DataGlobalConstants::SecInHour;
2574 2595750 : ZnAirRpt(ZoneLoop).VentilVdotStdDensity = ZnAirRpt(ZoneLoop).VentilMdot / AirDensity;
2575 2595750 : ZnAirRpt(ZoneLoop).VentilVolumeStdDensity = ZnAirRpt(ZoneLoop).VentilVdotStdDensity * TimeStepSys * DataGlobalConstants::SecInHour;
2576 :
2577 : // ZnAirRpt(ZoneLoop)%VentilFanElec = 0.0
2578 2595750 : ZnAirRpt(ZoneLoop).VentilAirTemp = 0.0;
2579 2595750 : ZnAirRpt(ZoneLoop).VentilHeatLoss = 0.0;
2580 2595750 : ZnAirRpt(ZoneLoop).VentilHeatGain = 0.0;
2581 2595750 : int VentZoneNum = 0; // Number of ventilation object per zone
2582 2595750 : Real64 VentZoneMassflow = 0.0; // Total mass flow rate per zone
2583 2595750 : Real64 VentZoneAirTemp = 0.0; // Average Zone inlet temperature
2584 :
2585 4454299 : for (int VentNum = 1; VentNum <= state.dataHeatBal->TotVentilation; ++VentNum) {
2586 1858549 : if (Ventilation(VentNum).ZonePtr == ZoneLoop) {
2587 : // moved into CalcAirFlowSimple
2588 : // ZnAirRpt(ZoneLoop)%VentilFanElec =
2589 : // ZnAirRpt(ZoneLoop)%VentilFanElec+Ventilation(VentNum)%FanPower*TimeStepSys*DataGlobalConstants::SecInHour()
2590 : // &
2591 : // *ADSCorrectionFactor
2592 43801 : if (ADSCorrectionFactor > 0) {
2593 42667 : ZnAirRpt(ZoneLoop).VentilAirTemp += Ventilation(VentNum).AirTemp * Ventilation(VentNum).MCP;
2594 42667 : VentZoneMassflow += Ventilation(VentNum).MCP;
2595 42667 : VentZoneAirTemp += Ventilation(VentNum).AirTemp;
2596 : } else {
2597 1134 : ZnAirRpt(ZoneLoop).VentilAirTemp = Zone(ZoneLoop).OutDryBulbTemp;
2598 : }
2599 : // Break the ventilation load into heat gain and loss components
2600 43801 : if (thisZoneHB.MAT > Ventilation(VentNum).AirTemp) {
2601 67830 : ZnAirRpt(ZoneLoop).VentilHeatLoss += Ventilation(VentNum).MCP * (thisZoneHB.MAT - Ventilation(VentNum).AirTemp) * TimeStepSys *
2602 33915 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2603 9886 : } else if (thisZoneHB.MAT <= Ventilation(VentNum).AirTemp) {
2604 19772 : ZnAirRpt(ZoneLoop).VentilHeatGain += Ventilation(VentNum).MCP * (Ventilation(VentNum).AirTemp - thisZoneHB.MAT) * TimeStepSys *
2605 9886 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2606 : }
2607 :
2608 43801 : ++VentZoneNum;
2609 43801 : if (VentZoneNum > 1) continue;
2610 :
2611 : // Report ventilation latent gains and losses
2612 42832 : H2OHtOfVap = PsyHgAirFnWTdb(thisZoneHB.ZoneAirHumRat, thisZoneHB.MAT);
2613 42832 : if (thisZoneHB.ZoneAirHumRat > state.dataEnvrn->OutHumRat) {
2614 66936 : ZnAirRpt(ZoneLoop).VentilLatentLoss = ZnAirRpt(ZoneLoop).VentilMdot * (thisZoneHB.ZoneAirHumRat - state.dataEnvrn->OutHumRat) *
2615 33468 : H2OHtOfVap * TimeStepSys * DataGlobalConstants::SecInHour;
2616 33468 : ZnAirRpt(ZoneLoop).VentilLatentGain = 0.0;
2617 9364 : } else if (thisZoneHB.ZoneAirHumRat <= state.dataEnvrn->OutHumRat) {
2618 18728 : ZnAirRpt(ZoneLoop).VentilLatentGain = ZnAirRpt(ZoneLoop).VentilMdot * (state.dataEnvrn->OutHumRat - thisZoneHB.ZoneAirHumRat) *
2619 9364 : H2OHtOfVap * TimeStepSys * DataGlobalConstants::SecInHour;
2620 9364 : ZnAirRpt(ZoneLoop).VentilLatentLoss = 0.0;
2621 : }
2622 : // Total ventilation losses and gains
2623 85664 : TotalLoad = ZnAirRpt(ZoneLoop).VentilHeatGain + ZnAirRpt(ZoneLoop).VentilLatentGain - ZnAirRpt(ZoneLoop).VentilHeatLoss -
2624 42832 : ZnAirRpt(ZoneLoop).VentilLatentLoss;
2625 42832 : if (TotalLoad > 0) {
2626 1011 : ZnAirRpt(ZoneLoop).VentilTotalGain = TotalLoad * ADSCorrectionFactor;
2627 1011 : ZnAirRpt(ZoneLoop).VentilTotalLoss = 0.0;
2628 : } else {
2629 41821 : ZnAirRpt(ZoneLoop).VentilTotalGain = 0.0;
2630 41821 : ZnAirRpt(ZoneLoop).VentilTotalLoss = -TotalLoad * ADSCorrectionFactor;
2631 : }
2632 : }
2633 : }
2634 :
2635 2595750 : if (ADSCorrectionFactor > 0 && VentZoneNum > 1 && VentZoneMassflow > 0.0) {
2636 357 : ZnAirRpt(ZoneLoop).VentilAirTemp /= VentZoneMassflow;
2637 2595393 : } else if (ADSCorrectionFactor > 0 && VentZoneNum == 1) {
2638 40729 : ZnAirRpt(ZoneLoop).VentilAirTemp = VentZoneAirTemp;
2639 : } else { // Just in case
2640 2554664 : ZnAirRpt(ZoneLoop).VentilAirTemp = Zone(ZoneLoop).OutDryBulbTemp;
2641 : }
2642 :
2643 : // Report mixing sensible and latent loads
2644 2595750 : MixSenLoad(ZoneLoop) = 0.0; // Initialize arrays to zero before starting to sum
2645 2595750 : MixLatLoad(ZoneLoop) = 0.0;
2646 2595750 : ZnAirRpt(ZoneLoop).MixVolume = 0.0; // zero reported volume prior to summations below
2647 2595750 : ZnAirRpt(ZoneLoop).MixVdotCurDensity = 0.0; // zero reported volume flow rate prior to summations below
2648 2595750 : ZnAirRpt(ZoneLoop).MixVdotStdDensity = 0.0; // zero reported volume flow rate prior to summations below
2649 2595750 : ZnAirRpt(ZoneLoop).MixMass = 0.0; // ! zero reported mass prior to summations below
2650 2595750 : ZnAirRpt(ZoneLoop).MixMdot = 0.0; // ! zero reported mass flow rate prior to summations below
2651 : // MixingLoad = 0.0d0
2652 :
2653 4610682 : for (int MixNum = 1; MixNum <= state.dataHeatBal->TotMixing; ++MixNum) {
2654 2014932 : if ((Mixing(MixNum).ZonePtr == ZoneLoop) && Mixing(MixNum).ReportFlag) {
2655 27047 : auto &fromZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(Mixing(MixNum).FromZone);
2656 : // MixSenLoad(ZoneLoop) = MixSenLoad(ZoneLoop)+MCPM(ZoneLoop)*MAT(Mixing(MixNum)%FromZone)
2657 : // H2OHtOfVap = PsyHgAirFnWTdb(ZoneAirHumRat(ZoneLoop), MAT(ZoneLoop))
2658 : // Per Jan 17, 2008 conference call, agreed to use average conditions for Rho, Cp and Hfg
2659 : // and to recalculate the report variable using end of time step temps and humrats
2660 108188 : AirDensity = PsyRhoAirFnPbTdbW(state,
2661 27047 : state.dataEnvrn->OutBaroPress,
2662 27047 : (thisZoneHB.MAT + fromZoneHB.MAT) / 2.0,
2663 27047 : (thisZoneHB.ZoneAirHumRat + fromZoneHB.ZoneAirHumRat) / 2.0,
2664 54094 : std::string());
2665 27047 : CpAir = PsyCpAirFnW((thisZoneHB.ZoneAirHumRat + fromZoneHB.ZoneAirHumRat) / 2.0);
2666 27047 : ZnAirRpt(ZoneLoop).MixVolume +=
2667 27047 : Mixing(MixNum).DesiredAirFlowRate * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2668 27047 : ZnAirRpt(ZoneLoop).MixVdotCurDensity += Mixing(MixNum).DesiredAirFlowRate * ADSCorrectionFactor;
2669 27047 : ZnAirRpt(ZoneLoop).MixMass +=
2670 27047 : Mixing(MixNum).DesiredAirFlowRate * AirDensity * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2671 27047 : ZnAirRpt(ZoneLoop).MixMdot += Mixing(MixNum).DesiredAirFlowRate * AirDensity * ADSCorrectionFactor;
2672 27047 : ZnAirRpt(ZoneLoop).MixVdotStdDensity +=
2673 27047 : Mixing(MixNum).DesiredAirFlowRate * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
2674 27047 : MixSenLoad(ZoneLoop) += Mixing(MixNum).DesiredAirFlowRate * AirDensity * CpAir * (thisZoneHB.MAT - fromZoneHB.MAT);
2675 27047 : H2OHtOfVap = PsyHgAirFnWTdb((thisZoneHB.ZoneAirHumRat + fromZoneHB.ZoneAirHumRat) / 2.0, (thisZoneHB.MAT + fromZoneHB.MAT) / 2.0);
2676 : // MixLatLoad(ZoneLoop) = MixLatLoad(ZoneLoop)+MixingMassFlowZone(ZoneLoop)*(ZoneAirHumRat(ZoneLoop)- &
2677 : // ZoneAirHumRat(Mixing(MixNum)%FromZone))*H2OHtOfVap
2678 27047 : MixLatLoad(ZoneLoop) +=
2679 27047 : Mixing(MixNum).DesiredAirFlowRate * AirDensity * (thisZoneHB.ZoneAirHumRat - fromZoneHB.ZoneAirHumRat) * H2OHtOfVap;
2680 : }
2681 : }
2682 :
2683 2624602 : for (int MixNum = 1; MixNum <= state.dataHeatBal->TotCrossMixing; ++MixNum) {
2684 28852 : if ((CrossMixing(MixNum).ZonePtr == ZoneLoop) && CrossMixing(MixNum).ReportFlag) {
2685 4099 : auto &fromZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(CrossMixing(MixNum).FromZone);
2686 : // MixSenLoad(ZoneLoop) = MixSenLoad(ZoneLoop)+MCPM(ZoneLoop)*MAT(CrossMixing(MixNum)%FromZone)
2687 : // Per Jan 17, 2008 conference call, agreed to use average conditions for Rho, Cp and Hfg
2688 : // and to recalculate the report variable using end of time step temps and humrats
2689 16396 : AirDensity = PsyRhoAirFnPbTdbW(state,
2690 4099 : state.dataEnvrn->OutBaroPress,
2691 4099 : (thisZoneHB.MAT + fromZoneHB.MAT) / 2.0,
2692 4099 : (thisZoneHB.ZoneAirHumRat + fromZoneHB.ZoneAirHumRat) / 2.0,
2693 8198 : std::string());
2694 4099 : CpAir = PsyCpAirFnW((thisZoneHB.ZoneAirHumRat + fromZoneHB.ZoneAirHumRat) / 2.0);
2695 4099 : ZnAirRpt(ZoneLoop).MixVolume +=
2696 4099 : CrossMixing(MixNum).DesiredAirFlowRate * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2697 4099 : ZnAirRpt(ZoneLoop).MixVdotCurDensity += CrossMixing(MixNum).DesiredAirFlowRate * ADSCorrectionFactor;
2698 4099 : ZnAirRpt(ZoneLoop).MixMass +=
2699 4099 : CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2700 4099 : ZnAirRpt(ZoneLoop).MixMdot += CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * ADSCorrectionFactor;
2701 4099 : ZnAirRpt(ZoneLoop).MixVdotStdDensity +=
2702 4099 : CrossMixing(MixNum).DesiredAirFlowRate * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
2703 4099 : MixSenLoad(ZoneLoop) += CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * CpAir * (thisZoneHB.MAT - fromZoneHB.MAT);
2704 4099 : H2OHtOfVap = PsyHgAirFnWTdb((thisZoneHB.ZoneAirHumRat + fromZoneHB.ZoneAirHumRat) / 2.0, (thisZoneHB.MAT + fromZoneHB.MAT) / 2.0);
2705 : // MixLatLoad(ZoneLoop) = MixLatLoad(ZoneLoop)+MixingMassFlowZone(ZoneLoop)*(ZoneAirHumRat(ZoneLoop)- &
2706 : // ZoneAirHumRat(CrossMixing(MixNum)%FromZone))*H2OHtOfVap
2707 4099 : MixLatLoad(ZoneLoop) +=
2708 4099 : CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * (thisZoneHB.ZoneAirHumRat - fromZoneHB.ZoneAirHumRat) * H2OHtOfVap;
2709 : }
2710 28852 : if ((CrossMixing(MixNum).FromZone == ZoneLoop) && CrossMixing(MixNum).ReportFlag) {
2711 4099 : auto &mixingZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(CrossMixing(MixNum).ZonePtr);
2712 16396 : AirDensity = PsyRhoAirFnPbTdbW(state,
2713 4099 : state.dataEnvrn->OutBaroPress,
2714 4099 : (thisZoneHB.MAT + mixingZoneHB.MAT) / 2.0,
2715 4099 : (thisZoneHB.ZoneAirHumRat + mixingZoneHB.ZoneAirHumRat) / 2.0,
2716 8198 : std::string());
2717 4099 : CpAir = PsyCpAirFnW((thisZoneHB.ZoneAirHumRat + mixingZoneHB.ZoneAirHumRat) / 2.0);
2718 4099 : ZnAirRpt(ZoneLoop).MixVolume +=
2719 4099 : CrossMixing(MixNum).DesiredAirFlowRate * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2720 4099 : ZnAirRpt(ZoneLoop).MixVdotCurDensity += CrossMixing(MixNum).DesiredAirFlowRate * ADSCorrectionFactor;
2721 4099 : ZnAirRpt(ZoneLoop).MixMass +=
2722 4099 : CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2723 4099 : ZnAirRpt(ZoneLoop).MixMdot += CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * ADSCorrectionFactor;
2724 4099 : ZnAirRpt(ZoneLoop).MixVdotStdDensity +=
2725 4099 : CrossMixing(MixNum).DesiredAirFlowRate * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
2726 4099 : MixSenLoad(ZoneLoop) += CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * CpAir * (thisZoneHB.MAT - mixingZoneHB.MAT);
2727 4099 : H2OHtOfVap = PsyHgAirFnWTdb((thisZoneHB.ZoneAirHumRat + mixingZoneHB.ZoneAirHumRat) / 2.0, (thisZoneHB.MAT + mixingZoneHB.MAT) / 2.0);
2728 4099 : MixLatLoad(ZoneLoop) +=
2729 4099 : CrossMixing(MixNum).DesiredAirFlowRate * AirDensity * (thisZoneHB.ZoneAirHumRat - mixingZoneHB.ZoneAirHumRat) * H2OHtOfVap;
2730 : }
2731 : }
2732 :
2733 2595750 : if (state.dataHeatBal->TotRefDoorMixing > 0) {
2734 : // IF(ZoneLoop .NE. NumOfZones)THEN !Refrigeration Door Mixing
2735 : // Note - do each Pair a Single time, so must do increment reports for both zones
2736 : // Can't have a pair that has ZoneA zone number = NumOfZones because organized
2737 : // in input with lowest zone # first no matter how input in idf
2738 11956 : if (RefDoorMixing(ZoneLoop).RefDoorMixFlag) { // .TRUE. for both zoneA and zoneB
2739 4270 : if (RefDoorMixing(ZoneLoop).ZonePtr == ZoneLoop) {
2740 5124 : for (int j = 1; j <= RefDoorMixing(ZoneLoop).NumRefDoorConnections; ++j) {
2741 : // Capture impact when zoneloop is the 'primary zone'
2742 : // that is, the zone of a pair with the lower zone number
2743 2562 : if (RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) > 0.0) {
2744 1431 : int ZoneB = RefDoorMixing(ZoneLoop).MateZonePtr(j);
2745 1431 : auto &zoneBHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneB);
2746 5724 : AirDensity = PsyRhoAirFnPbTdbW(state,
2747 1431 : state.dataEnvrn->OutBaroPress,
2748 1431 : (thisZoneHB.MAT + zoneBHB.MAT) / 2.0,
2749 1431 : (thisZoneHB.ZoneAirHumRat + zoneBHB.ZoneAirHumRat) / 2.0,
2750 2862 : std::string());
2751 1431 : CpAir = PsyCpAirFnW((thisZoneHB.ZoneAirHumRat + zoneBHB.ZoneAirHumRat) / 2.0);
2752 1431 : H2OHtOfVap =
2753 1431 : PsyHgAirFnWTdb((thisZoneHB.ZoneAirHumRat + zoneBHB.ZoneAirHumRat) / 2.0, (thisZoneHB.MAT + zoneBHB.MAT) / 2.0);
2754 1431 : ZnAirRpt(ZoneLoop).MixVolume +=
2755 1431 : RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2756 1431 : ZnAirRpt(ZoneLoop).MixVdotCurDensity += RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * ADSCorrectionFactor;
2757 2862 : ZnAirRpt(ZoneLoop).MixMass += RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * AirDensity * TimeStepSys *
2758 1431 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2759 1431 : ZnAirRpt(ZoneLoop).MixMdot += RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * AirDensity * ADSCorrectionFactor;
2760 1431 : ZnAirRpt(ZoneLoop).MixVdotStdDensity +=
2761 1431 : RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
2762 1431 : MixSenLoad(ZoneLoop) +=
2763 1431 : RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * AirDensity * CpAir * (thisZoneHB.MAT - zoneBHB.MAT);
2764 4293 : MixLatLoad(ZoneLoop) += RefDoorMixing(ZoneLoop).VolRefDoorFlowRate(j) * AirDensity *
2765 2862 : (thisZoneHB.ZoneAirHumRat - zoneBHB.ZoneAirHumRat) * H2OHtOfVap;
2766 : } // flow > 0
2767 : } // J-1, numref connections
2768 : } // zone A (zoneptr = zoneloop)
2769 23058 : for (int ZoneA = 1; ZoneA <= (ZoneLoop - 1); ++ZoneA) {
2770 18788 : auto &zoneAHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneA);
2771 : // Capture impact when zoneloop is the 'mating zone'
2772 : // that is, the zone of a pair with the higher zone number(matezoneptr = zoneloop)
2773 18788 : if (RefDoorMixing(ZoneA).RefDoorMixFlag) {
2774 14518 : for (int j = 1; j <= RefDoorMixing(ZoneA).NumRefDoorConnections; ++j) {
2775 5978 : if (RefDoorMixing(ZoneA).MateZonePtr(j) == ZoneLoop) {
2776 2562 : if (RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) > 0.0) {
2777 5724 : AirDensity = PsyRhoAirFnPbTdbW(state,
2778 1431 : state.dataEnvrn->OutBaroPress,
2779 1431 : (thisZoneHB.MAT + zoneAHB.MAT) / 2.0,
2780 1431 : (thisZoneHB.ZoneAirHumRat + zoneAHB.ZoneAirHumRat) / 2.0,
2781 2862 : std::string());
2782 1431 : CpAir = PsyCpAirFnW((thisZoneHB.ZoneAirHumRat + zoneAHB.ZoneAirHumRat) / 2.0);
2783 1431 : H2OHtOfVap = PsyHgAirFnWTdb((thisZoneHB.ZoneAirHumRat + zoneAHB.ZoneAirHumRat) / 2.0,
2784 1431 : (thisZoneHB.MAT + zoneAHB.MAT) / 2.0);
2785 2862 : ZnAirRpt(ZoneLoop).MixVolume += RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * TimeStepSys *
2786 1431 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2787 1431 : ZnAirRpt(ZoneLoop).MixVdotCurDensity += RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * ADSCorrectionFactor;
2788 2862 : ZnAirRpt(ZoneLoop).MixMass += RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * AirDensity * TimeStepSys *
2789 1431 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2790 1431 : ZnAirRpt(ZoneLoop).MixMdot += RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * AirDensity * ADSCorrectionFactor;
2791 1431 : ZnAirRpt(ZoneLoop).MixVdotStdDensity +=
2792 1431 : RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
2793 1431 : MixSenLoad(ZoneLoop) +=
2794 1431 : RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * AirDensity * CpAir * (thisZoneHB.MAT - zoneAHB.MAT);
2795 4293 : MixLatLoad(ZoneLoop) += RefDoorMixing(ZoneA).VolRefDoorFlowRate(j) * AirDensity *
2796 2862 : (thisZoneHB.ZoneAirHumRat - zoneAHB.ZoneAirHumRat) * H2OHtOfVap;
2797 : } // volflowrate > 0
2798 : } // matezoneptr (zoneB) = Zonelooop
2799 : } // NumRefDoorConnections
2800 : } // Refdoormix flag on ZoneA
2801 : } // zone A from 1 to (zoneloop - 1)
2802 : } // Refdoormix flag on zoneloop
2803 : } //(TotRefDoorMixing .GT. 0)
2804 : // end refrigeration door mixing reports
2805 :
2806 : // MixingLoad(ZoneLoop) = MCPM(ZoneLoop)*MAT(ZoneLoop) - MixSenLoad(ZoneLoop)
2807 2595750 : if (MixSenLoad(ZoneLoop) > 0.0) {
2808 17144 : ZnAirRpt(ZoneLoop).MixHeatLoss = MixSenLoad(ZoneLoop) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2809 17144 : ZnAirRpt(ZoneLoop).MixHeatGain = 0.0;
2810 : } else {
2811 2578606 : ZnAirRpt(ZoneLoop).MixHeatLoss = 0.0;
2812 2578606 : ZnAirRpt(ZoneLoop).MixHeatGain = -MixSenLoad(ZoneLoop) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2813 : }
2814 : // Report mixing latent loads
2815 : // MixingLoad(ZoneLoop) = MixLatLoad(ZoneLoop)
2816 2595750 : if (MixLatLoad(ZoneLoop) > 0.0) {
2817 16441 : ZnAirRpt(ZoneLoop).MixLatentLoss = MixLatLoad(ZoneLoop) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2818 16441 : ZnAirRpt(ZoneLoop).MixLatentGain = 0.0;
2819 : } else {
2820 2579309 : ZnAirRpt(ZoneLoop).MixLatentLoss = 0.0;
2821 2579309 : ZnAirRpt(ZoneLoop).MixLatentGain = -MixLatLoad(ZoneLoop) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2822 : }
2823 : // Total Mixing losses and gains
2824 2595750 : TotalLoad =
2825 2595750 : ZnAirRpt(ZoneLoop).MixHeatGain + ZnAirRpt(ZoneLoop).MixLatentGain - ZnAirRpt(ZoneLoop).MixHeatLoss - ZnAirRpt(ZoneLoop).MixLatentLoss;
2826 2595750 : if (TotalLoad > 0) {
2827 8552 : ZnAirRpt(ZoneLoop).MixTotalGain = TotalLoad * ADSCorrectionFactor;
2828 8552 : ZnAirRpt(ZoneLoop).MixTotalLoss = 0.0;
2829 : } else {
2830 2587198 : ZnAirRpt(ZoneLoop).MixTotalGain = 0.0;
2831 2587198 : ZnAirRpt(ZoneLoop).MixTotalLoss = -TotalLoad * ADSCorrectionFactor;
2832 : }
2833 :
2834 : // Reporting combined outdoor air flows
2835 2601144 : for (int j = 1; j <= state.dataHeatBal->TotZoneAirBalance; ++j) {
2836 10788 : if (state.dataHeatBal->ZoneAirBalance(j).BalanceMethod == DataHeatBalance::AirBalance::Quadrature &&
2837 5394 : ZoneLoop == state.dataHeatBal->ZoneAirBalance(j).ZonePtr) {
2838 1798 : if (thisZoneHB.MAT > Zone(ZoneLoop).OutDryBulbTemp) {
2839 3314 : ZnAirRpt(ZoneLoop).OABalanceHeatLoss = thisZoneHB.MDotCPOA * (thisZoneHB.MAT - Zone(ZoneLoop).OutDryBulbTemp) * TimeStepSys *
2840 1657 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2841 1657 : ZnAirRpt(ZoneLoop).OABalanceHeatGain = 0.0;
2842 : } else {
2843 141 : ZnAirRpt(ZoneLoop).OABalanceHeatLoss = 0.0;
2844 282 : ZnAirRpt(ZoneLoop).OABalanceHeatGain = -thisZoneHB.MDotCPOA * (thisZoneHB.MAT - Zone(ZoneLoop).OutDryBulbTemp) * TimeStepSys *
2845 141 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2846 : }
2847 1798 : H2OHtOfVap = PsyHgAirFnWTdb(state.dataEnvrn->OutHumRat, Zone(ZoneLoop).OutDryBulbTemp);
2848 1798 : if (thisZoneHB.ZoneAirHumRat > state.dataEnvrn->OutHumRat) {
2849 396 : ZnAirRpt(ZoneLoop).OABalanceLatentLoss = thisZoneHB.MDotOA * (thisZoneHB.ZoneAirHumRat - state.dataEnvrn->OutHumRat) *
2850 198 : H2OHtOfVap * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2851 198 : ZnAirRpt(ZoneLoop).OABalanceLatentGain = 0.0;
2852 1600 : } else if (thisZoneHB.ZoneAirHumRat <= state.dataEnvrn->OutHumRat) {
2853 3200 : ZnAirRpt(ZoneLoop).OABalanceLatentGain = thisZoneHB.MDotOA * (state.dataEnvrn->OutHumRat - thisZoneHB.ZoneAirHumRat) *
2854 1600 : H2OHtOfVap * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2855 1600 : ZnAirRpt(ZoneLoop).OABalanceLatentLoss = 0.0;
2856 : }
2857 : // Total ventilation losses and gains
2858 3596 : TotalLoad = ZnAirRpt(ZoneLoop).OABalanceHeatGain + ZnAirRpt(ZoneLoop).OABalanceLatentGain - ZnAirRpt(ZoneLoop).OABalanceHeatLoss -
2859 1798 : ZnAirRpt(ZoneLoop).OABalanceLatentLoss;
2860 1798 : if (TotalLoad > 0) {
2861 164 : ZnAirRpt(ZoneLoop).OABalanceTotalGain = TotalLoad * ADSCorrectionFactor;
2862 164 : ZnAirRpt(ZoneLoop).OABalanceTotalLoss = 0.0;
2863 : } else {
2864 1634 : ZnAirRpt(ZoneLoop).OABalanceTotalGain = 0.0;
2865 1634 : ZnAirRpt(ZoneLoop).OABalanceTotalLoss = -TotalLoad * ADSCorrectionFactor;
2866 : }
2867 1798 : ZnAirRpt(ZoneLoop).OABalanceMass = (thisZoneHB.MDotOA) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2868 1798 : ZnAirRpt(ZoneLoop).OABalanceMdot = (thisZoneHB.MDotOA) * ADSCorrectionFactor;
2869 1798 : AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRatAvg, std::string());
2870 1798 : ZnAirRpt(ZoneLoop).OABalanceVolumeCurDensity =
2871 1798 : (thisZoneHB.MDotOA / AirDensity) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2872 1798 : ZnAirRpt(ZoneLoop).OABalanceAirChangeRate = ZnAirRpt(ZoneLoop).OABalanceVolumeCurDensity / (TimeStepSys * Zone(ZoneLoop).Volume);
2873 1798 : ZnAirRpt(ZoneLoop).OABalanceVdotCurDensity = (thisZoneHB.MDotOA / AirDensity) * ADSCorrectionFactor;
2874 1798 : AirDensity = state.dataEnvrn->StdRhoAir;
2875 1798 : ZnAirRpt(ZoneLoop).OABalanceVolumeStdDensity =
2876 1798 : (thisZoneHB.MDotOA / AirDensity) * TimeStepSys * DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2877 1798 : ZnAirRpt(ZoneLoop).OABalanceVdotStdDensity = (thisZoneHB.MDotOA / AirDensity) * ADSCorrectionFactor;
2878 1798 : ZnAirRpt(ZoneLoop).OABalanceFanElec = ZnAirRpt(ZoneLoop).VentilFanElec;
2879 : }
2880 : }
2881 : // Reports exfiltration loss
2882 2595750 : H2OHtOfVap = PsyHgAirFnWTdb(state.dataEnvrn->OutHumRat, Zone(ZoneLoop).OutDryBulbTemp);
2883 2595750 : ZnAirRpt(ZoneLoop).SysInletMass = 0;
2884 2595750 : ZnAirRpt(ZoneLoop).SysOutletMass = 0;
2885 2595750 : if (!ZoneEquipConfig(ZoneLoop).IsControlled) {
2886 363525 : for (int k = 1; k <= ZoneEquipConfig(ZoneLoop).NumInletNodes; ++k) {
2887 0 : ZnAirRpt(ZoneLoop).SysInletMass += state.dataLoopNodes->Node(ZoneEquipConfig(ZoneLoop).InletNode(k)).MassFlowRate * TimeStepSys *
2888 0 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2889 : }
2890 363525 : for (int k = 1; k <= ZoneEquipConfig(ZoneLoop).NumExhaustNodes; ++k) {
2891 0 : ZnAirRpt(ZoneLoop).SysOutletMass += state.dataLoopNodes->Node(ZoneEquipConfig(ZoneLoop).ExhaustNode(k)).MassFlowRate * TimeStepSys *
2892 0 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2893 : }
2894 363525 : for (int k = 1; k <= ZoneEquipConfig(ZoneLoop).NumReturnNodes; ++k) {
2895 0 : ZnAirRpt(ZoneLoop).SysOutletMass += state.dataLoopNodes->Node(ZoneEquipConfig(ZoneLoop).ReturnNode(k)).MassFlowRate * TimeStepSys *
2896 0 : DataGlobalConstants::SecInHour * ADSCorrectionFactor;
2897 : }
2898 : }
2899 :
2900 7787250 : ZnAirRpt(ZoneLoop).ExfilMass = ZnAirRpt(ZoneLoop).InfilMass + ZnAirRpt(ZoneLoop).VentilMass + ZnAirRpt(ZoneLoop).MixMass +
2901 5191500 : ZnAirRpt(ZoneLoop).OABalanceMass + ZnAirRpt(ZoneLoop).SysInletMass - ZnAirRpt(ZoneLoop).SysOutletMass; // kg
2902 7787250 : ZnAirRpt(ZoneLoop).ExfilSensiLoss = ZnAirRpt(ZoneLoop).ExfilMass / (TimeStepSys * DataGlobalConstants::SecInHour) *
2903 5191500 : (thisZoneHB.MAT - Zone(ZoneLoop).OutDryBulbTemp) * CpAir; // W
2904 7787250 : ZnAirRpt(ZoneLoop).ExfilLatentLoss = ZnAirRpt(ZoneLoop).ExfilMass / (TimeStepSys * DataGlobalConstants::SecInHour) *
2905 5191500 : (thisZoneHB.ZoneAirHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap;
2906 2595750 : ZnAirRpt(ZoneLoop).ExfilTotalLoss = ZnAirRpt(ZoneLoop).ExfilLatentLoss + ZnAirRpt(ZoneLoop).ExfilSensiLoss;
2907 :
2908 2595750 : state.dataHeatBal->ZoneTotalExfiltrationHeatLoss += ZnAirRpt(ZoneLoop).ExfilTotalLoss * TimeStepSys * DataGlobalConstants::SecInHour;
2909 2595750 : state.dataHeatBal->ZoneTotalExhaustHeatLoss += ZnAirRpt(ZoneLoop).ExhTotalLoss * TimeStepSys * DataGlobalConstants::SecInHour;
2910 : }
2911 : }
2912 :
2913 2568313 : void SetHeatToReturnAirFlag(EnergyPlusData &state)
2914 : {
2915 :
2916 : // SUBROUTINE INFORMATION:
2917 : // AUTHOR Fred Buhl
2918 : // DATE WRITTEN February 2008
2919 :
2920 : // PURPOSE OF THIS SUBROUTINE:
2921 : // This sets some flags at the air loop and zone level: these flags indicate
2922 : // whether an air loop represents a "unitary" system, and whether the system is operating
2923 : // in a on/off (cycling fan) mode. At the zone level flags are set to indicate whether
2924 : // the zone is served by a zonal system only, and whether the air loop serving the zone (idf any)
2925 : // is in cycling fan mode. Using this information, the subroutine sets a flag at the zone level
2926 : // to tell ManageZoneAirUpdates (predict and correct) what to do with the heat to return air.
2927 :
2928 : // METHODOLOGY EMPLOYED:
2929 : // Uses program data structures AirLoopControlInfo and ZoneEquipInfo
2930 :
2931 : // Using/Aliasing
2932 2568313 : auto &NumPrimaryAirSys = state.dataHVACGlobal->NumPrimaryAirSys;
2933 : using ScheduleManager::CheckScheduleValue;
2934 : using ScheduleManager::GetCurrentScheduleValue;
2935 : using ScheduleManager::GetScheduleMaxValue;
2936 :
2937 2568313 : bool CyclingFan(false); // TRUE means air loop operates in cycling fan mode at some point
2938 :
2939 2568313 : auto &AirLoopControlInfo(state.dataAirLoop->AirLoopControlInfo);
2940 2568313 : auto &ZoneEquipConfig(state.dataZoneEquip->ZoneEquipConfig);
2941 :
2942 2568313 : if (!state.dataHVACGlobal->AirLoopsSimOnce) return;
2943 :
2944 1780535 : if (state.dataHVACMgr->MyOneTimeFlag) {
2945 : // set the air loop Any Continuous Fan flag
2946 1941 : for (int AirLoopNum = 1; AirLoopNum <= NumPrimaryAirSys; ++AirLoopNum) {
2947 1172 : if (AirLoopControlInfo(AirLoopNum).UnitarySys) { // for unitary systems check the cycling fan schedule
2948 469 : if (AirLoopControlInfo(AirLoopNum).CycFanSchedPtr > 0) {
2949 444 : Real64 CycFanMaxVal = GetScheduleMaxValue(state, AirLoopControlInfo(AirLoopNum).CycFanSchedPtr);
2950 444 : if (CycFanMaxVal > 0.0) {
2951 245 : AirLoopControlInfo(AirLoopNum).AnyContFan = true;
2952 : } else {
2953 199 : AirLoopControlInfo(AirLoopNum).AnyContFan = false;
2954 : }
2955 : } else { // no schedule means always cycling fan
2956 25 : AirLoopControlInfo(AirLoopNum).AnyContFan = false;
2957 : }
2958 : } else { // for nonunitary (central) all systems are continuous fan
2959 703 : AirLoopControlInfo(AirLoopNum).AnyContFan = true;
2960 : }
2961 : }
2962 : // check to see if a controlled zone is served exclusively by a zonal system
2963 5571 : for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
2964 4802 : bool airLoopFound = false;
2965 9035 : for (int zoneInNode = 1; zoneInNode <= ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
2966 4233 : if (ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) > 0) {
2967 3455 : airLoopFound = true;
2968 : }
2969 : }
2970 4802 : if (!airLoopFound && ZoneEquipConfig(ControlledZoneNum).NumInletNodes == ZoneEquipConfig(ControlledZoneNum).NumExhaustNodes) {
2971 1158 : ZoneEquipConfig(ControlledZoneNum).ZonalSystemOnly = true;
2972 : }
2973 : }
2974 : // issue warning messages if zone is served by a zonal system or a cycling system and the input calls for
2975 : // heat gain to return air
2976 5571 : for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
2977 4802 : if (!ZoneEquipConfig(ControlledZoneNum).IsControlled) continue;
2978 4094 : CyclingFan = false;
2979 8327 : for (int zoneInNode = 1; zoneInNode <= ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
2980 4233 : int AirLoopNum = ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
2981 4233 : if (AirLoopNum > 0) {
2982 3455 : if (AirLoopControlInfo(AirLoopNum).CycFanSchedPtr > 0) {
2983 561 : CyclingFan = CheckScheduleValue(state, AirLoopControlInfo(AirLoopNum).CycFanSchedPtr, 0.0);
2984 : }
2985 : }
2986 : }
2987 4094 : if (ZoneEquipConfig(ControlledZoneNum).ZonalSystemOnly || CyclingFan) {
2988 825 : auto const &thisZone = state.dataHeatBal->Zone(ControlledZoneNum);
2989 825 : if (thisZone.RefrigCaseRA) {
2990 12 : ShowWarningError(state,
2991 8 : "For zone=" + thisZone.Name + " return air cooling by refrigerated cases will be applied to the zone air.");
2992 4 : ShowContinueError(state, " This zone has no return air or is served by an on/off HVAC system.");
2993 : }
2994 28598 : for (int LightNum = 1; LightNum <= state.dataHeatBal->TotLights; ++LightNum) {
2995 27793 : if (state.dataHeatBal->Lights(LightNum).ZonePtr != ControlledZoneNum) continue;
2996 855 : if (state.dataHeatBal->Lights(LightNum).FractionReturnAir > 0.0) {
2997 20 : ShowWarningError(state, "For zone=" + thisZone.Name + " return air heat gain from lights will be applied to the zone air.");
2998 20 : ShowContinueError(state, " This zone has no return air or is served by an on/off HVAC system.");
2999 20 : break;
3000 : }
3001 : }
3002 1650 : for (int spaceNum : thisZone.spaceIndexes) {
3003 825 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
3004 7880 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
3005 7055 : if (state.dataSurface->SurfWinAirflowDestination(SurfNum) == DataSurfaces::WindowAirFlowDestination::Return) {
3006 0 : ShowWarningError(
3007 0 : state, "For zone=" + thisZone.Name + " return air heat gain from air flow windows will be applied to the zone air.");
3008 0 : ShowContinueError(state, " This zone has no return air or is served by an on/off HVAC system.");
3009 : }
3010 : }
3011 : }
3012 : }
3013 : }
3014 769 : state.dataHVACMgr->MyOneTimeFlag = false;
3015 : }
3016 :
3017 : // set the air loop fan operation mode
3018 4276201 : for (int AirLoopNum = 1; AirLoopNum <= NumPrimaryAirSys; ++AirLoopNum) {
3019 2495666 : if (AirLoopControlInfo(AirLoopNum).CycFanSchedPtr > 0) {
3020 858027 : if (GetCurrentScheduleValue(state, AirLoopControlInfo(AirLoopNum).CycFanSchedPtr) == 0.0) {
3021 386648 : AirLoopControlInfo(AirLoopNum).FanOpMode = CycFanCycCoil;
3022 : } else {
3023 471379 : AirLoopControlInfo(AirLoopNum).FanOpMode = ContFanCycCoil;
3024 : }
3025 : }
3026 : }
3027 : // set the zone level NoHeatToReturnAir flag
3028 : // if any air loop in the zone is continuous fan, then set NoHeatToReturnAir = false and sort it out node-by-node
3029 12704141 : for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
3030 10923606 : auto &thisZone = state.dataHeatBal->Zone(ControlledZoneNum);
3031 10923606 : if (!ZoneEquipConfig(ControlledZoneNum).IsControlled) continue;
3032 9326278 : thisZone.NoHeatToReturnAir = true;
3033 9326278 : if (!ZoneEquipConfig(ControlledZoneNum).ZonalSystemOnly) {
3034 9748153 : for (int zoneInNode = 1; zoneInNode <= ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
3035 8703085 : int AirLoopNum = ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
3036 8703085 : if (AirLoopNum > 0) {
3037 7963301 : if (AirLoopControlInfo(AirLoopNum).FanOpMode == ContFanCycCoil) {
3038 7417643 : thisZone.NoHeatToReturnAir = false;
3039 7417643 : break;
3040 : }
3041 : }
3042 : }
3043 : }
3044 : }
3045 : }
3046 :
3047 2969485 : void UpdateZoneInletConvergenceLog(EnergyPlusData &state)
3048 : {
3049 :
3050 2969485 : std::array<Real64, DataConvergParams::ConvergLogStackDepth> tmpRealARR = {0};
3051 :
3052 25290215 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
3053 :
3054 41861791 : for (int NodeIndex = 1; NodeIndex <= state.dataConvergeParams->ZoneInletConvergence(ZoneNum).NumInletNodes; ++NodeIndex) {
3055 19541061 : int NodeNum = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum;
3056 :
3057 19541061 : tmpRealARR = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio;
3058 19541061 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio[0] = state.dataLoopNodes->Node(NodeNum).HumRat;
3059 195410610 : for (int logIndex = 1; logIndex < DataConvergParams::ConvergLogStackDepth; logIndex++) {
3060 175869549 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio[logIndex] = tmpRealARR[logIndex - 1];
3061 : }
3062 :
3063 19541061 : tmpRealARR = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate;
3064 19541061 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate[0] =
3065 19541061 : state.dataLoopNodes->Node(NodeNum).MassFlowRate;
3066 195410610 : for (int logIndex = 1; logIndex < DataConvergParams::ConvergLogStackDepth; logIndex++) {
3067 175869549 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate[logIndex] = tmpRealARR[logIndex - 1];
3068 : }
3069 :
3070 19541061 : tmpRealARR = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature;
3071 19541061 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature[0] = state.dataLoopNodes->Node(NodeNum).Temp;
3072 195410610 : for (int logIndex = 1; logIndex < DataConvergParams::ConvergLogStackDepth; logIndex++) {
3073 175869549 : state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature[logIndex] = tmpRealARR[logIndex - 1];
3074 : }
3075 : }
3076 : }
3077 2969485 : }
3078 :
3079 2638872 : void CheckAirLoopFlowBalance(EnergyPlusData &state)
3080 : {
3081 : // Check for unbalanced airloop
3082 2638872 : if (!state.dataGlobal->WarmupFlag && state.dataHVACGlobal->AirLoopsSimOnce) {
3083 1081804 : for (int AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) {
3084 646074 : auto &thisAirLoopFlow(state.dataAirLoop->AirLoopFlow(AirLoopNum));
3085 646074 : if (!thisAirLoopFlow.FlowError) {
3086 645984 : Real64 unbalancedExhaustDelta = thisAirLoopFlow.SupFlow - thisAirLoopFlow.OAFlow - thisAirLoopFlow.SysRetFlow;
3087 645984 : if (unbalancedExhaustDelta > SmallMassFlow) {
3088 3 : ShowSevereError(state,
3089 2 : "CheckAirLoopFlowBalance: AirLoopHVAC " + state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name +
3090 : " is unbalanced. Supply is > return plus outdoor air.");
3091 1 : ShowContinueErrorTimeStamp(state, "");
3092 3 : ShowContinueError(state,
3093 2 : format(" Flows [m3/s at standard density]: Supply={:.6R} Return={:.6R} Outdoor Air={:.6R}",
3094 2 : thisAirLoopFlow.SupFlow / state.dataEnvrn->StdRhoAir,
3095 2 : thisAirLoopFlow.SysRetFlow / state.dataEnvrn->StdRhoAir,
3096 3 : thisAirLoopFlow.OAFlow / state.dataEnvrn->StdRhoAir));
3097 1 : ShowContinueError(state, format(" Imbalance={:.6R}", unbalancedExhaustDelta / state.dataEnvrn->StdRhoAir));
3098 1 : ShowContinueError(state, " This error will only be reported once per system.");
3099 1 : thisAirLoopFlow.FlowError = true;
3100 : }
3101 : }
3102 : }
3103 : }
3104 2638872 : }
3105 :
3106 2313 : } // namespace EnergyPlus::HVACManager
|