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

Generated by: LCOV version 2.0-1