LCOV - code coverage report
Current view: top level - EnergyPlus - HVACManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 51.7 % 1684 870
Test Date: 2025-05-22 16:09:37 Functions: 100.0 % 18 18

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

Generated by: LCOV version 2.0-1