LCOV - code coverage report
Current view: top level - EnergyPlus - HVACManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 67.2 % 1712 1150
Test Date: 2025-06-02 07:23:51 Functions: 88.9 % 18 16

            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      2828212 : 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      2828212 :     Real64 ZoneTempChange(0.0); // change in zone air temperature from timestep t-1 to t
     154              : 
     155      2828212 :     auto &s_hbfs = state.dataHeatBalFanSys;
     156              : 
     157              :     // SYSTEM INITIALIZATION
     158      2828212 :     if (state.dataHVACMgr->TriggerGetAFN) {
     159          801 :         state.dataHVACMgr->TriggerGetAFN = false;
     160          801 :         DisplayString(state, "Initializing HVAC");
     161          801 :         state.afn->manage_balance(); // first call only gets input and returns.
     162              :     }
     163              : 
     164     23362447 :     for (auto &thisZoneHB : state.dataZoneTempPredictorCorrector->zoneHeatBalance) {
     165     20534235 :         thisZoneHB.ZT = thisZoneHB.MAT;
     166              :         // save for use with thermal comfort control models (Fang, Pierce, and KSU)
     167     20534235 :         thisZoneHB.ZTAV = 0.0;
     168     20534235 :         thisZoneHB.airHumRatAvg = 0.0;
     169      2828212 :     }
     170     23411047 :     for (auto &thisSpaceHB : state.dataZoneTempPredictorCorrector->spaceHeatBalance) {
     171     20582835 :         thisSpaceHB.ZT = thisSpaceHB.MAT;
     172              :         // save for use with thermal comfort control models (Fang, Pierce, and KSU)
     173     20582835 :         thisSpaceHB.ZTAV = 0.0;
     174     20582835 :         thisSpaceHB.airHumRatAvg = 0.0;
     175      2828212 :     }
     176              : 
     177     23357246 :     for (auto &zoneTstatSetpt : s_hbfs->zoneTstatSetpts) {
     178     20529034 :         zoneTstatSetpt.setptHiAver = zoneTstatSetpt.setptLoAver = 0.0;
     179              :     }
     180              : 
     181      2828212 :     state.dataHVACMgr->PrintedWarmup = false;
     182      2828212 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
     183        39675 :         state.dataContaminantBalance->OutdoorCO2 = state.dataContaminantBalance->Contaminant.CO2OutdoorSched->getCurrentVal();
     184        39675 :         state.dataContaminantBalance->ZoneAirCO2Avg = 0.0;
     185              :     }
     186      2828212 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
     187         7089 :         state.dataContaminantBalance->OutdoorGC = state.dataContaminantBalance->Contaminant.genericOutdoorSched->getCurrentVal();
     188         7089 :         if (allocated(state.dataContaminantBalance->ZoneAirGCAvg)) {
     189         7089 :             state.dataContaminantBalance->ZoneAirGCAvg = 0.0;
     190              :         }
     191              :     }
     192              : 
     193      2828212 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataHVACMgr->MyEnvrnFlag) {
     194         6496 :         state.dataHVACGlobal->AirLoopsSimOnce = false;
     195         6496 :         state.dataHVACMgr->MyEnvrnFlag = false;
     196         6496 :         state.dataHVACGlobal->NumOfSysTimeStepsLastZoneTimeStep = 1;
     197         6496 :         state.dataHVACGlobal->PreviousTimeStep = state.dataGlobal->TimeStepZone;
     198              :     }
     199      2828212 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     200      2821716 :         state.dataHVACMgr->MyEnvrnFlag = true;
     201              :     }
     202              : 
     203      2828212 :     state.dataHeatBalFanSys->QRadSurfAFNDuct = 0.0;
     204              : 
     205      2828212 :     state.dataHVACGlobal->SysTimeElapsed = 0.0;
     206      2828212 :     state.dataHVACGlobal->TimeStepSys = state.dataGlobal->TimeStepZone;
     207      2828212 :     state.dataHVACGlobal->TimeStepSysSec = state.dataHVACGlobal->TimeStepSys * Constant::rSecsInHour;
     208      2828212 :     state.dataHVACGlobal->FirstTimeStepSysFlag = true;
     209      2828212 :     state.dataHVACGlobal->ShortenTimeStepSys = false;
     210      2828212 :     state.dataHVACGlobal->UseZoneTimeStepHistory = true;
     211      2828212 :     PriorTimeStep = state.dataGlobal->TimeStepZone;
     212      2828212 :     state.dataHVACGlobal->NumOfSysTimeSteps = 1;
     213      2828212 :     state.dataHVACGlobal->FracTimeStepZone = state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
     214              : 
     215              :     bool anyEMSRan;
     216      2828212 :     EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::BeginTimestepBeforePredictor, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point
     217              : 
     218      2828212 :     OutAirNodeManager::SetOutAirNodes(state);
     219              : 
     220      2828212 :     RefrigeratedCase::ManageRefrigeratedCaseRacks(state);
     221              : 
     222              :     // ZONE INITIALIZATION  'Get Zone Setpoints'
     223      5656424 :     ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     224              :                                                      DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints,
     225              :                                                      ZoneTempChange,
     226      2828212 :                                                      state.dataHVACGlobal->ShortenTimeStepSys,
     227      2828212 :                                                      state.dataHVACGlobal->UseZoneTimeStepHistory,
     228              :                                                      PriorTimeStep);
     229      2828212 :     if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     230        83406 :         ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     231              :                                                                        DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints,
     232        41703 :                                                                        state.dataHVACGlobal->ShortenTimeStepSys,
     233        41703 :                                                                        state.dataHVACGlobal->UseZoneTimeStepHistory,
     234              :                                                                        PriorTimeStep);
     235              :     }
     236              : 
     237      2828212 :     Avail::ManageHybridVentilation(state);
     238              : 
     239      2828212 :     ZoneEquipmentManager::CalcAirFlowSimple(state);
     240      2828212 :     if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
     241        95691 :         state.afn->RollBackFlag = false;
     242        95691 :         state.afn->manage_balance(false);
     243              :     }
     244              : 
     245      2828212 :     SetHeatToReturnAirFlag(state);
     246              : 
     247     23362447 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
     248     20534235 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum);
     249     20534235 :         thisZoneHB.SysDepZoneLoadsLagged = thisZoneHB.SysDepZoneLoads;
     250     20534235 :         if (state.dataHeatBal->doSpaceHeatBalance) {
     251       113364 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
     252              :                 // SpaceHB ToDo: For now allocate by space volume frac
     253        64782 :                 state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).SysDepZoneLoadsLagged =
     254        64782 :                     thisZoneHB.SysDepZoneLoads * state.dataHeatBal->space(spaceNum).fracZoneVolume;
     255        48582 :             }
     256              :         }
     257              :     }
     258      2828212 :     IndoorGreen::SimIndoorGreen(state);
     259      2828212 :     InternalHeatGains::UpdateInternalGainValues(state, true, true);
     260              : 
     261      5656424 :     ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     262              :                                                      DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep,
     263              :                                                      ZoneTempChange,
     264      2828212 :                                                      state.dataHVACGlobal->ShortenTimeStepSys,
     265      2828212 :                                                      state.dataHVACGlobal->UseZoneTimeStepHistory,
     266              :                                                      PriorTimeStep);
     267              : 
     268      2828212 :     if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     269        83406 :         ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     270              :                                                                        DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep,
     271        41703 :                                                                        state.dataHVACGlobal->ShortenTimeStepSys,
     272        41703 :                                                                        state.dataHVACGlobal->UseZoneTimeStepHistory,
     273              :                                                                        PriorTimeStep);
     274              :     }
     275              : 
     276      2828212 :     SimHVAC(state);
     277      2828212 :     if (state.dataGlobal->AnyIdealCondEntSetPointInModel && state.dataGlobal->MetersHaveBeenInitialized && !state.dataGlobal->WarmupFlag) {
     278          384 :         state.dataGlobal->RunOptCondEntTemp = true;
     279         1935 :         while (state.dataGlobal->RunOptCondEntTemp) {
     280         1551 :             SimHVAC(state);
     281              :         }
     282              :     }
     283              : 
     284      2828212 :     WaterManager::ManageWaterInits(state);
     285              : 
     286              :     // Only simulate once per zone timestep; must be after SimHVAC
     287      2828212 :     if (state.dataHVACGlobal->FirstTimeStepSysFlag && state.dataGlobal->MetersHaveBeenInitialized) {
     288      1989307 :         DemandManager::ManageDemand(state);
     289              :     }
     290              : 
     291      2828212 :     state.dataGlobal->BeginTimeStepFlag = false; // At this point, we have been through the first pass through SimHVAC so this needs to be set
     292              : 
     293      5656424 :     ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     294              :                                                      DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep,
     295              :                                                      ZoneTempChange,
     296      2828212 :                                                      state.dataHVACGlobal->ShortenTimeStepSys,
     297      2828212 :                                                      state.dataHVACGlobal->UseZoneTimeStepHistory,
     298              :                                                      PriorTimeStep);
     299      2828212 :     if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     300        83406 :         ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     301              :                                                                        DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep,
     302        41703 :                                                                        state.dataHVACGlobal->ShortenTimeStepSys,
     303        41703 :                                                                        state.dataHVACGlobal->UseZoneTimeStepHistory,
     304              :                                                                        PriorTimeStep);
     305              :     }
     306              : 
     307      2828212 :     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       357242 :         int ZTempTrendsNumSysSteps = int(ZoneTempChange / state.dataConvergeParams->MaxZoneTempDiff + 1.0); // add 1 for truncation
     311       357242 :         state.dataHVACGlobal->NumOfSysTimeSteps = min(ZTempTrendsNumSysSteps, state.dataHVACGlobal->LimitNumSysSteps);
     312              :         // then determine timestep length for even distribution, protect div by zero
     313       357242 :         if (state.dataHVACGlobal->NumOfSysTimeSteps > 0) {
     314       357242 :             state.dataHVACGlobal->TimeStepSys = state.dataGlobal->TimeStepZone / state.dataHVACGlobal->NumOfSysTimeSteps;
     315              :         }
     316       357242 :         state.dataHVACGlobal->TimeStepSys = max(state.dataHVACGlobal->TimeStepSys, state.dataConvergeParams->MinTimeStepSys);
     317       357242 :         state.dataHVACGlobal->TimeStepSysSec = state.dataHVACGlobal->TimeStepSys * Constant::rSecsInHour;
     318       357242 :         state.dataHVACGlobal->UseZoneTimeStepHistory = false;
     319       357242 :         state.dataHVACGlobal->ShortenTimeStepSys = true;
     320              : 
     321              :     } else {
     322      2470970 :         state.dataHVACGlobal->NumOfSysTimeSteps = 1;
     323      2470970 :         state.dataHVACGlobal->UseZoneTimeStepHistory = true;
     324              :     }
     325              : 
     326      2828212 :     if (state.dataHVACGlobal->UseZoneTimeStepHistory) {
     327      2470970 :         state.dataHVACGlobal->PreviousTimeStep = state.dataGlobal->TimeStepZone;
     328              :     }
     329      6417042 :     for (int SysTimestepLoop = 1; SysTimestepLoop <= state.dataHVACGlobal->NumOfSysTimeSteps; ++SysTimestepLoop) {
     330      3588830 :         if (state.dataGlobal->stopSimulation) {
     331            0 :             break;
     332              :         }
     333              : 
     334      3588830 :         if (state.dataHVACGlobal->TimeStepSys < state.dataGlobal->TimeStepZone) {
     335              : 
     336      1068368 :             Avail::ManageHybridVentilation(state);
     337      1068368 :             ZoneEquipmentManager::CalcAirFlowSimple(state, SysTimestepLoop);
     338      1068368 :             if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
     339        57457 :                 state.afn->RollBackFlag = false;
     340        57457 :                 state.afn->manage_balance(false);
     341              :             }
     342              : 
     343      1068368 :             InternalHeatGains::UpdateInternalGainValues(state, true, true);
     344              : 
     345      2136736 :             ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     346              :                                                              DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep,
     347              :                                                              ZoneTempChange,
     348      1068368 :                                                              state.dataHVACGlobal->ShortenTimeStepSys,
     349      1068368 :                                                              state.dataHVACGlobal->UseZoneTimeStepHistory,
     350              :                                                              PriorTimeStep);
     351              : 
     352      1068368 :             if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     353        45012 :                 ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     354              :                                                                                DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep,
     355        22506 :                                                                                state.dataHVACGlobal->ShortenTimeStepSys,
     356        22506 :                                                                                state.dataHVACGlobal->UseZoneTimeStepHistory,
     357              :                                                                                PriorTimeStep);
     358              :             }
     359      1068368 :             SimHVAC(state);
     360              : 
     361      1068368 :             if (state.dataGlobal->AnyIdealCondEntSetPointInModel && state.dataGlobal->MetersHaveBeenInitialized && !state.dataGlobal->WarmupFlag) {
     362           76 :                 state.dataGlobal->RunOptCondEntTemp = true;
     363          639 :                 while (state.dataGlobal->RunOptCondEntTemp) {
     364          563 :                     SimHVAC(state);
     365              :                 }
     366              :             }
     367              : 
     368      1068368 :             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      1068368 :             state.dataHVACGlobal->ShortenTimeStepSys = false;
     372              : 
     373      2136736 :             ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     374              :                                                              DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep,
     375              :                                                              ZoneTempChange,
     376      1068368 :                                                              state.dataHVACGlobal->ShortenTimeStepSys,
     377      1068368 :                                                              state.dataHVACGlobal->UseZoneTimeStepHistory,
     378              :                                                              PriorTimeStep);
     379      1068368 :             if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     380        45012 :                 ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     381              :                                                                                DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep,
     382        22506 :                                                                                state.dataHVACGlobal->ShortenTimeStepSys,
     383        22506 :                                                                                state.dataHVACGlobal->UseZoneTimeStepHistory,
     384              :                                                                                PriorTimeStep);
     385              :             }
     386              : 
     387      2136736 :             ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     388              :                                                              DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories,
     389              :                                                              ZoneTempChange,
     390      1068368 :                                                              state.dataHVACGlobal->ShortenTimeStepSys,
     391      1068368 :                                                              state.dataHVACGlobal->UseZoneTimeStepHistory,
     392              :                                                              PriorTimeStep);
     393      1068368 :             if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     394        45012 :                 ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     395              :                                                                                DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories,
     396        22506 :                                                                                state.dataHVACGlobal->ShortenTimeStepSys,
     397        22506 :                                                                                state.dataHVACGlobal->UseZoneTimeStepHistory,
     398              :                                                                                PriorTimeStep);
     399              :             }
     400      1068368 :             state.dataHVACGlobal->PreviousTimeStep = state.dataHVACGlobal->TimeStepSys;
     401              :         }
     402              : 
     403      3588830 :         state.dataHVACGlobal->FracTimeStepZone = state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
     404              : 
     405     31768998 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
     406     28180168 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     407     28180168 :             thisZoneHB.ZTAV += thisZoneHB.ZT * state.dataHVACGlobal->FracTimeStepZone;
     408     28180168 :             thisZoneHB.airHumRatAvg += thisZoneHB.airHumRat * state.dataHVACGlobal->FracTimeStepZone;
     409              :             // Space temps are always used, regardless of doSpaceHeatBalance setting
     410     56418200 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
     411     28238032 :                 auto &thisSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum);
     412     28238032 :                 thisSpaceHB.ZTAV += thisSpaceHB.ZT * state.dataHVACGlobal->FracTimeStepZone;
     413     28238032 :                 thisSpaceHB.airHumRatAvg += thisSpaceHB.airHumRat * state.dataHVACGlobal->FracTimeStepZone;
     414     28180168 :             }
     415     28180168 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
     416       337352 :                 state.dataContaminantBalance->ZoneAirCO2Avg(ZoneNum) +=
     417       337352 :                     state.dataContaminantBalance->ZoneAirCO2(ZoneNum) * state.dataHVACGlobal->FracTimeStepZone;
     418              :             }
     419     28180168 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
     420       233429 :                 state.dataContaminantBalance->ZoneAirGCAvg(ZoneNum) +=
     421       233429 :                     state.dataContaminantBalance->ZoneAirGC(ZoneNum) * state.dataHVACGlobal->FracTimeStepZone;
     422              :             }
     423     28180168 :             if (state.dataZoneTempPredictorCorrector->NumOnOffCtrZone > 0) {
     424       230574 :                 auto &zoneTstatSetpt = s_hbfs->zoneTstatSetpts(ZoneNum);
     425       230574 :                 zoneTstatSetpt.setptHiAver += zoneTstatSetpt.setptHi * state.dataHVACGlobal->FracTimeStepZone;
     426       230574 :                 zoneTstatSetpt.setptLoAver += zoneTstatSetpt.setptLo * state.dataHVACGlobal->FracTimeStepZone;
     427              :             }
     428              :         }
     429              : 
     430      3588830 :         ZoneTempPredictorCorrector::DetectOscillatingZoneTemp(state);
     431      3588830 :         UpdateZoneListAndGroupLoads(state);           // Must be called before UpdateDataandReport(OutputProcessor::TimeStepType::TimeStepSystem)
     432      3588830 :         IceThermalStorage::UpdateIceFractions(state); // Update fraction of ice stored in TES
     433      3588830 :         WaterManager::ManageWater(state);
     434              :         // update electricity data for net, purchased, sold etc.
     435      3588830 :         bool DummyLogical = false;
     436      3588830 :         state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(state, false, DummyLogical, true);
     437              : 
     438              :         // Update the plant and condenser loop capacitance model temperature history.
     439      3588830 :         PlantManager::UpdateNodeThermalHistory(state);
     440              : 
     441      3588830 :         if (state.dataOutRptTab->displayHeatEmissionsSummary) {
     442      1419538 :             OutputReportTabular::CalcHeatEmissionReport(state);
     443              :         }
     444              : 
     445      3588830 :         EMSManager::ManageEMS(
     446      7177660 :             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      3588830 :         if (!state.dataGlobal->WarmupFlag) {
     450       763271 :             if (state.dataGlobal->DoOutputReporting && !state.dataGlobal->ZoneSizingCalc) {
     451       624372 :                 NodeInputManager::CalcMoreNodeInfo(state);
     452       624372 :                 Pollution::CalculatePollution(state);
     453       624372 :                 SystemReports::InitEnergyReports(state);
     454       624372 :                 SystemReports::ReportSystemEnergyUse(state);
     455              :             }
     456       763271 :             if (state.dataGlobal->DoOutputReporting || (state.dataGlobal->ZoneSizingCalc && state.dataGlobal->CompLoadReportIsReq)) {
     457       636404 :                 ReportAirHeatBalance(state);
     458       636404 :                 if (state.dataGlobal->ZoneSizingCalc) {
     459        12032 :                     OutputReportTabular::GatherComponentLoadsHVAC(state);
     460              :                 }
     461              :             }
     462       763271 :             if (state.dataGlobal->DoOutputReporting) {
     463       624372 :                 SystemReports::ReportVentilationLoads(state);
     464       624372 :                 UpdateDataandReport(state, OutputProcessor::TimeStepType::System);
     465      1239533 :                 if (state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeDesignDay ||
     466       615161 :                     state.dataGlobal->KindOfSim == Constant::KindOfSim::HVACSizeRunPeriodDesign) {
     467         9211 :                     if (state.dataHVACSizingSimMgr->hvacSizingSimulationManager) {
     468         9211 :                         state.dataHVACSizingSimMgr->hvacSizingSimulationManager->UpdateSizingLogsSystemStep(state);
     469              :                     }
     470              :                 }
     471       624372 :                 OutputReportTabular::UpdateTabularReports(state, OutputProcessor::TimeStepType::System);
     472              :             }
     473       763271 :             if (state.dataGlobal->ZoneSizingCalc) {
     474       138899 :                 ZoneEquipmentManager::UpdateZoneSizing(state, Constant::CallIndicator::DuringDay);
     475       138899 :                 SizingManager::UpdateFacilitySizing(state, Constant::CallIndicator::DuringDay);
     476              :             }
     477       763271 :             EIRPlantLoopHeatPumps::EIRPlantLoopHeatPump::checkConcurrentOperation(state);
     478      2825559 :         } 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      2825559 :         } else if (state.dataSysVars->UpdateDataDuringWarmupExternalInterface) { // added for FMI
     525         3891 :             if (state.dataGlobal->BeginDayFlag && !state.dataEnvrn->PrintEnvrnStampWarmupPrinted) {
     526           30 :                 state.dataEnvrn->PrintEnvrnStampWarmup = true;
     527           30 :                 state.dataEnvrn->PrintEnvrnStampWarmupPrinted = true;
     528              :             }
     529         3891 :             if (!state.dataGlobal->BeginDayFlag) {
     530         3851 :                 state.dataEnvrn->PrintEnvrnStampWarmupPrinted = false;
     531              :             }
     532         3891 :             if (state.dataEnvrn->PrintEnvrnStampWarmup) {
     533           30 :                 if (state.dataReportFlag->PrintEndDataDictionary && state.dataGlobal->DoOutputReporting && !state.dataHVACMgr->PrintedWarmup) {
     534            3 :                     print(state.files.eso, "{}\n", EndOfHeaderString);
     535            3 :                     print(state.files.mtr, "{}\n", EndOfHeaderString);
     536            3 :                     state.dataReportFlag->PrintEndDataDictionary = false;
     537              :                 }
     538           30 :                 if (state.dataGlobal->DoOutputReporting && !state.dataHVACMgr->PrintedWarmup) {
     539           30 :                     print(state.files.eso,
     540              :                           EnvironmentStampFormatStr,
     541              :                           "1",
     542           60 :                           "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
     543           30 :                           state.dataEnvrn->Latitude,
     544           30 :                           state.dataEnvrn->Longitude,
     545           30 :                           state.dataEnvrn->TimeZoneNumber,
     546           30 :                           state.dataEnvrn->Elevation);
     547           30 :                     print(state.files.mtr,
     548              :                           EnvironmentStampFormatStr,
     549              :                           "1",
     550           60 :                           "Warmup {" + state.dataReportFlag->cWarmupDay + "} " + state.dataEnvrn->EnvironmentName,
     551           30 :                           state.dataEnvrn->Latitude,
     552           30 :                           state.dataEnvrn->Longitude,
     553           30 :                           state.dataEnvrn->TimeZoneNumber,
     554           30 :                           state.dataEnvrn->Elevation);
     555           30 :                     state.dataEnvrn->PrintEnvrnStampWarmup = false;
     556              :                 }
     557           30 :                 state.dataHVACMgr->PrintedWarmup = true;
     558              :             }
     559         3891 :             UpdateDataandReport(state, OutputProcessor::TimeStepType::System);
     560              :         }
     561      3588830 :         EMSManager::ManageEMS(
     562      7177660 :             state, EMSManager::EMSCallFrom::EndSystemTimestepAfterHVACReporting, anyEMSRan, ObjexxFCL::Optional_int_const()); // EMS calling point
     563              :         // UPDATE SYSTEM CLOCKS
     564      3588830 :         state.dataHVACGlobal->SysTimeElapsed += state.dataHVACGlobal->TimeStepSys;
     565              : 
     566      3588830 :         state.dataHVACGlobal->FirstTimeStepSysFlag = false;
     567              :     } // system time step  loop (loops once if no downstepping)
     568              : 
     569     23362447 :     for (auto &thisZoneHB : state.dataZoneTempPredictorCorrector->zoneHeatBalance) {
     570     20534235 :         thisZoneHB.ZTAVComf = thisZoneHB.ZTAV;
     571     20534235 :         thisZoneHB.airHumRatAvgComf = thisZoneHB.airHumRatAvg;
     572      2828212 :     }
     573     23411047 :     for (auto &thisSpaceHB : state.dataZoneTempPredictorCorrector->spaceHeatBalance) {
     574     20582835 :         thisSpaceHB.ZTAVComf = thisSpaceHB.ZTAV;
     575     20582835 :         thisSpaceHB.airHumRatAvgComf = thisSpaceHB.airHumRatAvg;
     576      2828212 :     }
     577              : 
     578      5656424 :     ZoneTempPredictorCorrector::ManageZoneAirUpdates(state,
     579              :                                                      DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories,
     580              :                                                      ZoneTempChange,
     581      2828212 :                                                      state.dataHVACGlobal->ShortenTimeStepSys,
     582      2828212 :                                                      state.dataHVACGlobal->UseZoneTimeStepHistory,
     583              :                                                      PriorTimeStep);
     584      2828212 :     if (state.dataContaminantBalance->Contaminant.SimulateContaminants) {
     585        83406 :         ZoneContaminantPredictorCorrector::ManageZoneContaminanUpdates(state,
     586              :                                                                        DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories,
     587        41703 :                                                                        state.dataHVACGlobal->ShortenTimeStepSys,
     588        41703 :                                                                        state.dataHVACGlobal->UseZoneTimeStepHistory,
     589              :                                                                        PriorTimeStep);
     590              :     }
     591              : 
     592      2828212 :     state.dataHVACGlobal->NumOfSysTimeStepsLastZoneTimeStep = state.dataHVACGlobal->NumOfSysTimeSteps;
     593              : 
     594      2828212 :     DemandManager::UpdateDemandManagers(state);
     595              : 
     596              :     // DO FINAL UPDATE OF RECORD KEEPING VARIABLES
     597              :     // Report the Node Data to Aid in Debugging
     598      2828212 :     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      2828212 : }
     686              : 
     687      3898932 : 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      3898932 :     bool constexpr SimWithPlantFlowUnlocked(false);
     709      3898932 :     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      3898932 :     Real64 constexpr sum_ConvergLogStackARR(-45);
     721      3898932 :     Real64 constexpr square_sum_ConvergLogStackARR(2025);
     722      3898932 :     Real64 constexpr sum_square_ConvergLogStackARR(285);
     723              : 
     724      3898932 :     int NumPrimaryAirSys = state.dataHVACGlobal->NumPrimaryAirSys;
     725              : 
     726              :     // Initialize all of the simulation flags to true for the first iteration
     727      3898932 :     state.dataHVACGlobal->SimZoneEquipmentFlag = true;
     728      3898932 :     state.dataHVACGlobal->SimNonZoneEquipmentFlag = true;
     729      3898932 :     state.dataHVACGlobal->SimAirLoopsFlag = true;
     730      3898932 :     state.dataHVACGlobal->SimPlantLoopsFlag = true;
     731      3898932 :     state.dataHVACGlobal->SimElecCircuitsFlag = true;
     732      3898932 :     FirstHVACIteration = true;
     733              : 
     734      3898932 :     if (state.dataAirLoop->AirLoopInputsFilled) {
     735      7449902 :         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      4596036 :             e.CoolingActiveFlag = false;
     738              :             // Reset air loop control info for heating coil active flag (used in OA controller for HX control)
     739      4596036 :             e.HeatingActiveFlag = false;
     740              :             // reset outside air system HX to off first time through
     741      4596036 :             e.HeatRecoveryBypass = true;
     742              :             // set HX check status flag to check for custom control in MixedAir.cc
     743      4596036 :             e.CheckHeatRecoveryBypassStatus = true;
     744              :             // set OA comp simulated flag to false
     745      4596036 :             e.OASysComponentsSimulated = false;
     746              :             // set economizer flow locked flag to false, will reset if custom HX control is used
     747      4596036 :             e.EconomizerFlowLocked = false;
     748              :             // set air loop resim flags for when heat recovery is used and air loop needs another iteration
     749      4596036 :             e.HeatRecoveryResimFlag = true;
     750      4596036 :             e.HeatRecoveryResimFlag2 = false;
     751      4596036 :             e.ResimAirLoopFlag = false;
     752      2853866 :         }
     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      3898932 :     state.dataHVACMgr->HVACManageIteration = 0;
     760      3898932 :     state.dataPlnt->PlantManageSubIterations = 0;
     761      3898932 :     state.dataPlnt->PlantManageHalfLoopCalls = 0;
     762      3898932 :     PlantUtilities::SetAllPlantSimFlagsToValue(state, true);
     763      3898932 :     if (!state.dataHVACMgr->SimHVACIterSetup) {
     764         2403 :         SetupOutputVariable(state,
     765              :                             "HVAC System Solver Iteration Count",
     766              :                             Constant::Units::None,
     767          801 :                             state.dataHVACMgr->HVACManageIteration,
     768              :                             OutputProcessor::TimeStepType::System,
     769              :                             OutputProcessor::StoreType::Sum,
     770              :                             "SimHVAC");
     771         1602 :         SetupOutputVariable(state,
     772              :                             "Air System Solver Iteration Count",
     773              :                             Constant::Units::None,
     774          801 :                             state.dataHVACMgr->RepIterAir,
     775              :                             OutputProcessor::TimeStepType::System,
     776              :                             OutputProcessor::StoreType::Sum,
     777              :                             "SimHVAC");
     778         3204 :         SetupOutputVariable(state,
     779              :                             "Air System Relief Air Total Heat Loss Energy",
     780              :                             Constant::Units::J,
     781          801 :                             state.dataHeatBal->SysTotalHVACReliefHeatLoss,
     782              :                             OutputProcessor::TimeStepType::System,
     783              :                             OutputProcessor::StoreType::Sum,
     784              :                             "SimHVAC");
     785         3204 :         SetupOutputVariable(state,
     786              :                             "HVAC System Total Heat Rejection Energy",
     787              :                             Constant::Units::J,
     788          801 :                             state.dataHeatBal->SysTotalHVACRejectHeatLoss,
     789              :                             OutputProcessor::TimeStepType::System,
     790              :                             OutputProcessor::StoreType::Sum,
     791              :                             "SimHVAC");
     792          801 :         SetPointManager::ManageSetPoints(state); // need to call this before getting plant loop data so setpoint checks can complete okay
     793          801 :         PlantManager::GetPlantLoopData(state);
     794          801 :         PlantManager::GetPlantInput(state);
     795          801 :         PlantManager::SetupInitialPlantCallingOrder(state);
     796          801 :         PlantManager::SetupBranchControlTypes(state); // new routine to do away with input for branch control type
     797          801 :         PlantManager::SetupReports(state);
     798          801 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
     799           76 :             PlantCondLoopOperation::SetupPlantEMSActuators(state);
     800              :         }
     801              : 
     802          801 :         if (state.dataPlnt->TotNumLoops > 0) {
     803         1389 :             SetupOutputVariable(state,
     804              :                                 "Plant Solver Sub Iteration Count",
     805              :                                 Constant::Units::None,
     806          463 :                                 state.dataPlnt->PlantManageSubIterations,
     807              :                                 OutputProcessor::TimeStepType::System,
     808              :                                 OutputProcessor::StoreType::Sum,
     809              :                                 "SimHVAC");
     810          926 :             SetupOutputVariable(state,
     811              :                                 "Plant Solver Half Loop Calls Count",
     812              :                                 Constant::Units::None,
     813          463 :                                 state.dataPlnt->PlantManageHalfLoopCalls,
     814              :                                 OutputProcessor::TimeStepType::System,
     815              :                                 OutputProcessor::StoreType::Sum,
     816              :                                 "SimHVAC");
     817         1621 :             for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
     818              :                 // init plant sizing numbers in main plant data structure
     819         1158 :                 PlantManager::InitOneTimePlantSizingInfo(state, LoopNum);
     820              :             }
     821              :         }
     822          801 :         state.dataHVACMgr->SimHVACIterSetup = true;
     823              :     }
     824              : 
     825      3898932 :     if (state.dataGlobal->ZoneSizingCalc) {
     826      1044266 :         ZoneEquipmentManager::ManageZoneEquipment(
     827      1044266 :             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      1044266 :         NonZoneEquipmentManager::ManageNonZoneEquipment(state, FirstHVACIteration, state.dataHVACGlobal->SimNonZoneEquipmentFlag);
     830      1044266 :         state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
     831      1044266 :             state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
     832      1044266 :         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      2854666 :     ResetHVACControl(state);
     840              : 
     841              :     // Before the HVAC simulation, call ManageSetPoints to set all the HVAC node setpoints
     842      2854666 :     bool anyEMSRan = false;
     843      2854666 :     EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::BeforeHVACManagers, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point
     844              : 
     845      2854666 :     SetPointManager::ManageSetPoints(state);
     846              : 
     847              :     // re-initialize plant loop and nodes.
     848      2854666 :     PlantManager::ReInitPlantLoopsAtFirstHVACIteration(state);
     849              : 
     850              :     // Before the HVAC simulation, call ManageSystemAvailability to set the system on/off flags
     851      2854666 :     Avail::ManageSystemAvailability(state);
     852              : 
     853      2854666 :     EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::AfterHVACManagers, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point
     854      2854666 :     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      2854666 :     SimSelectedEquipment(state,
     860      2854666 :                          state.dataHVACGlobal->SimAirLoopsFlag,
     861      2854666 :                          state.dataHVACGlobal->SimZoneEquipmentFlag,
     862      2854666 :                          state.dataHVACGlobal->SimNonZoneEquipmentFlag,
     863      2854666 :                          state.dataHVACGlobal->SimPlantLoopsFlag,
     864      2854666 :                          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      2854666 :     state.dataHVACGlobal->SimPlantLoopsFlag = true;
     872      2854666 :     PlantUtilities::SetAllPlantSimFlagsToValue(state, true); // set so loop to simulate at least once on non-first hvac
     873              : 
     874      2854666 :     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     11694050 :     while ((state.dataHVACGlobal->SimAirLoopsFlag || state.dataHVACGlobal->SimZoneEquipmentFlag || state.dataHVACGlobal->SimNonZoneEquipmentFlag ||
     881     11968963 :             state.dataHVACGlobal->SimPlantLoopsFlag || state.dataHVACGlobal->SimElecCircuitsFlag) &&
     882      3130021 :            (state.dataHVACMgr->HVACManageIteration <= state.dataConvergeParams->MaxIter)) {
     883              : 
     884      3127471 :         if (state.dataGlobal->stopSimulation) {
     885            0 :             break;
     886              :         }
     887              : 
     888      3127471 :         EMSManager::ManageEMS(state, EMSManager::EMSCallFrom::HVACIterationLoop, anyEMSRan, ObjexxFCL::Optional_int_const()); // calling point id
     889              : 
     890              :         // Manages the various component simulations
     891      3127471 :         SimSelectedEquipment(state,
     892      3127471 :                              state.dataHVACGlobal->SimAirLoopsFlag,
     893      3127471 :                              state.dataHVACGlobal->SimZoneEquipmentFlag,
     894      3127471 :                              state.dataHVACGlobal->SimNonZoneEquipmentFlag,
     895      3127471 :                              state.dataHVACGlobal->SimPlantLoopsFlag,
     896      3127471 :                              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      3127471 :         UpdateZoneInletConvergenceLog(state);
     904              : 
     905      3127471 :         ++state.dataHVACMgr->HVACManageIteration; // Increment the iteration counter
     906              : 
     907      3127471 :         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       139040 :             state.dataHVACGlobal->SimAirLoopsFlag = true;
     910              :         }
     911      3127471 :         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        46164 :             state.dataHVACGlobal->SimAirLoopsFlag = true;
     914        46164 :             state.dataHVACGlobal->SimZoneEquipmentFlag = true;
     915              :         }
     916              :     }
     917      2854666 :     if (state.dataGlobal->AnyPlantInModel) {
     918      1454358 :         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         8319 :             state.dataHVACGlobal->SimAirLoopsFlag = false;
     922         8319 :             state.dataHVACGlobal->SimZoneEquipmentFlag = false;
     923         8319 :             state.dataHVACGlobal->SimNonZoneEquipmentFlag = false;
     924         8319 :             state.dataHVACGlobal->SimPlantLoopsFlag = true;
     925         8319 :             state.dataHVACGlobal->SimElecCircuitsFlag = false;
     926         8319 :             SimSelectedEquipment(state,
     927         8319 :                                  state.dataHVACGlobal->SimAirLoopsFlag,
     928         8319 :                                  state.dataHVACGlobal->SimZoneEquipmentFlag,
     929         8319 :                                  state.dataHVACGlobal->SimNonZoneEquipmentFlag,
     930         8319 :                                  state.dataHVACGlobal->SimPlantLoopsFlag,
     931         8319 :                                  state.dataHVACGlobal->SimElecCircuitsFlag,
     932              :                                  FirstHVACIteration,
     933              :                                  SimWithPlantFlowUnlocked);
     934              :             // now call for all non-plant simulation, but with plant flow lock on
     935         8319 :             state.dataHVACGlobal->SimAirLoopsFlag = true;
     936         8319 :             state.dataHVACGlobal->SimZoneEquipmentFlag = true;
     937         8319 :             state.dataHVACGlobal->SimNonZoneEquipmentFlag = true;
     938         8319 :             state.dataHVACGlobal->SimPlantLoopsFlag = false;
     939         8319 :             state.dataHVACGlobal->SimElecCircuitsFlag = true;
     940         8319 :             SimSelectedEquipment(state,
     941         8319 :                                  state.dataHVACGlobal->SimAirLoopsFlag,
     942         8319 :                                  state.dataHVACGlobal->SimZoneEquipmentFlag,
     943         8319 :                                  state.dataHVACGlobal->SimNonZoneEquipmentFlag,
     944         8319 :                                  state.dataHVACGlobal->SimPlantLoopsFlag,
     945         8319 :                                  state.dataHVACGlobal->SimElecCircuitsFlag,
     946              :                                  FirstHVACIteration,
     947              :                                  SimWithPlantFlowLocked);
     948         8319 :             UpdateZoneInletConvergenceLog(state);
     949              :             // now call for a last plant simulation
     950         8319 :             state.dataHVACGlobal->SimAirLoopsFlag = false;
     951         8319 :             state.dataHVACGlobal->SimZoneEquipmentFlag = false;
     952         8319 :             state.dataHVACGlobal->SimNonZoneEquipmentFlag = false;
     953         8319 :             state.dataHVACGlobal->SimPlantLoopsFlag = true;
     954         8319 :             state.dataHVACGlobal->SimElecCircuitsFlag = false;
     955         8319 :             SimSelectedEquipment(state,
     956         8319 :                                  state.dataHVACGlobal->SimAirLoopsFlag,
     957         8319 :                                  state.dataHVACGlobal->SimZoneEquipmentFlag,
     958         8319 :                                  state.dataHVACGlobal->SimNonZoneEquipmentFlag,
     959         8319 :                                  state.dataHVACGlobal->SimPlantLoopsFlag,
     960         8319 :                                  state.dataHVACGlobal->SimElecCircuitsFlag,
     961              :                                  FirstHVACIteration,
     962              :                                  SimWithPlantFlowUnlocked);
     963              :             // now call for a last all non-plant simulation, but with plant flow lock on
     964         8319 :             state.dataHVACGlobal->SimAirLoopsFlag = true;
     965         8319 :             state.dataHVACGlobal->SimZoneEquipmentFlag = true;
     966         8319 :             state.dataHVACGlobal->SimNonZoneEquipmentFlag = true;
     967         8319 :             state.dataHVACGlobal->SimPlantLoopsFlag = false;
     968         8319 :             state.dataHVACGlobal->SimElecCircuitsFlag = true;
     969         8319 :             SimSelectedEquipment(state,
     970         8319 :                                  state.dataHVACGlobal->SimAirLoopsFlag,
     971         8319 :                                  state.dataHVACGlobal->SimZoneEquipmentFlag,
     972         8319 :                                  state.dataHVACGlobal->SimNonZoneEquipmentFlag,
     973         8319 :                                  state.dataHVACGlobal->SimPlantLoopsFlag,
     974         8319 :                                  state.dataHVACGlobal->SimElecCircuitsFlag,
     975              :                                  FirstHVACIteration,
     976              :                                  SimWithPlantFlowLocked);
     977         8319 :             UpdateZoneInletConvergenceLog(state);
     978              :         }
     979              :     }
     980              : 
     981              :     // Test plant loop for errors
     982      6623321 :     for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
     983     11305965 :         for (DataPlant::LoopSideLocation LoopSide : DataPlant::LoopSideKeys) {
     984      7537310 :             PlantUtilities::CheckPlantMixerSplitterConsistency(state, LoopNum, LoopSide, FirstHVACIteration);
     985      7537310 :             PlantUtilities::CheckForRunawayPlantTemps(state, LoopNum, LoopSide);
     986              :         }
     987              :     }
     988              : 
     989      2854666 :     if ((state.dataHVACMgr->HVACManageIteration > state.dataConvergeParams->MaxIter) && (!state.dataGlobal->WarmupFlag)) {
     990          385 :         ++state.dataHVACMgr->ErrCount;
     991          385 :         if (state.dataHVACMgr->ErrCount < 15) {
     992          130 :             state.dataHVACMgr->ErrEnvironmentName = state.dataEnvrn->EnvironmentName;
     993          260 :             ShowWarningError(state,
     994          260 :                              format("SimHVAC: Maximum iterations ({}) exceeded for all HVAC loops, at {}, {} {}",
     995          130 :                                     state.dataConvergeParams->MaxIter,
     996          130 :                                     state.dataEnvrn->EnvironmentName,
     997          130 :                                     state.dataEnvrn->CurMnDy,
     998          260 :                                     General::CreateSysTimeIntervalString(state)));
     999          130 :             if (state.dataHVACGlobal->SimAirLoopsFlag) {
    1000          372 :                 ShowContinueError(state, "The solution for one or more of the Air Loop HVAC systems did not appear to converge");
    1001              :             }
    1002          130 :             if (state.dataHVACGlobal->SimZoneEquipmentFlag) {
    1003           54 :                 ShowContinueError(state, "The solution for zone HVAC equipment did not appear to converge");
    1004              :             }
    1005          130 :             if (state.dataHVACGlobal->SimNonZoneEquipmentFlag) {
    1006            0 :                 ShowContinueError(state, "The solution for non-zone equipment did not appear to converge");
    1007              :             }
    1008          130 :             if (state.dataHVACGlobal->SimPlantLoopsFlag) {
    1009            0 :                 ShowContinueError(state, "The solution for one or more plant systems did not appear to converge");
    1010              :             }
    1011          130 :             if (state.dataHVACGlobal->SimElecCircuitsFlag) {
    1012            0 :                 ShowContinueError(state, "The solution for on-site electric generators did not appear to converge");
    1013              :             }
    1014          130 :             if (state.dataHVACMgr->ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
    1015           51 :                 ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on each max iteration exceeded.");
    1016              :             }
    1017          130 :             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          255 :             if (state.dataEnvrn->EnvironmentName == state.dataHVACMgr->ErrEnvironmentName) {
    1715         2040 :                 ShowRecurringWarningErrorAtEnd(
    1716              :                     state,
    1717          510 :                     format("SimHVAC: Exceeding Maximum iterations for all HVAC loops, during {} continues", state.dataEnvrn->EnvironmentName),
    1718          255 :                     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      2854666 :     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      2854666 :     if (!state.dataGlobal->ZoneSizingCalc && !state.dataGlobal->SysSizingCalc) {
    1735      2854666 :         if (state.dataHVACMgr->MySetPointInit) {
    1736          800 :             if (state.dataLoopNodes->NumOfNodes > 0) {
    1737        65815 :                 for (auto &e : state.dataLoopNodes->Node) {
    1738        65083 :                     e.TempSetPoint = DataLoopNode::SensedNodeFlagValue;
    1739        65083 :                     e.HumRatSetPoint = DataLoopNode::SensedNodeFlagValue;
    1740        65083 :                     e.HumRatMin = DataLoopNode::SensedNodeFlagValue;
    1741        65083 :                     e.HumRatMax = DataLoopNode::SensedNodeFlagValue;
    1742        65083 :                     e.MassFlowRateSetPoint = DataLoopNode::SensedNodeFlagValue; // BG 5-26-2009 (being checked in HVACControllers.cc)
    1743              :                 }
    1744          732 :                 state.dataLoopNodes->DefaultNodeValues.TempSetPoint = DataLoopNode::SensedNodeFlagValue;
    1745          732 :                 state.dataLoopNodes->DefaultNodeValues.HumRatSetPoint = DataLoopNode::SensedNodeFlagValue;
    1746          732 :                 state.dataLoopNodes->DefaultNodeValues.HumRatMin = DataLoopNode::SensedNodeFlagValue;
    1747          732 :                 state.dataLoopNodes->DefaultNodeValues.HumRatMax = DataLoopNode::SensedNodeFlagValue;
    1748          732 :                 state.dataLoopNodes->DefaultNodeValues.MassFlowRateSetPoint =
    1749              :                     DataLoopNode::SensedNodeFlagValue; // BG 5-26-2009 (being checked in HVACControllers.cc)
    1750              :             }
    1751          800 :             state.dataHVACMgr->MySetPointInit = false;
    1752          800 :             state.dataHVACGlobal->DoSetPointTest = true;
    1753              :         } else {
    1754      2853866 :             state.dataHVACGlobal->DoSetPointTest = false;
    1755              :         }
    1756              : 
    1757      2854666 :         if (state.dataCoilCoolingDX->stillNeedToReportStandardRatings) {
    1758       967784 :             if (!state.dataGlobal->WarmupFlag) {
    1759          799 :                 CoilCoolingDX::reportAllStandardRatings(state);
    1760              :             }
    1761              :         }
    1762              :     }
    1763      2854666 :     if (state.dataHVACGlobal->SetPointErrorFlag) {
    1764            0 :         ShowFatalError(state, "Previous severe set point errors cause program termination");
    1765              :     }
    1766              : }
    1767              : 
    1768      6015413 : 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      6015413 :     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      6015413 :     if (LockPlantFlows) {
    1796        16638 :         PlantUtilities::SetAllFlowLocks(state, DataPlant::FlowLock::Locked);
    1797              :     } else {
    1798      5998775 :         PlantUtilities::SetAllFlowLocks(state, DataPlant::FlowLock::Unlocked);
    1799              :     }
    1800      6015413 :     PlantUtilities::ResetAllPlantInterConnectFlags(state);
    1801              : 
    1802      6015413 :     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         4670 :         ZoneEquipmentManager::ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipment, SimAirLoops);
    1809         4670 :         state.dataHVACMgr->MyEnvrnFlag2 = false;
    1810              :     }
    1811      6015413 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1812      5987868 :         state.dataHVACMgr->MyEnvrnFlag2 = true;
    1813              :     }
    1814              : 
    1815      6015413 :     if (FirstHVACIteration) {
    1816      2854666 :         state.dataHVACMgr->RepIterAir = 0;
    1817              :         // Call AirflowNetwork simulation to calculate air flows and pressures
    1818      2854666 :         if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    1819       129171 :             state.afn->manage_balance(FirstHVACIteration);
    1820              :         }
    1821      2854666 :         SimAirServingZones::ManageAirLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment);
    1822      2854666 :         state.dataAirLoop->AirLoopInputsFilled = true; // all air loop inputs have been read in
    1823      2854666 :         SimAirLoops = true; // Need to make sure that SimAirLoop is simulated at min twice to calculate PLR in some air loop equipment
    1824      2854666 :         state.dataHVACGlobal->AirLoopsSimOnce = true; // air loops simulated once for this environment
    1825      2854666 :         ResetTerminalUnitFlowLimits(state);
    1826      2854666 :         state.dataHVACMgr->FlowMaxAvailAlreadyReset = true;
    1827      2854666 :         ZoneEquipmentManager::ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipment, SimAirLoops);
    1828      2854666 :         SimZoneEquipment = true; // needs to be simulated at least twice for flow resolution to propagate to this routine
    1829      2854666 :         NonZoneEquipmentManager::ManageNonZoneEquipment(state, FirstHVACIteration, SimNonZoneEquipment);
    1830      2854666 :         state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
    1831      2854666 :             state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
    1832              : 
    1833      2854666 :         PlantManager::ManagePlantLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment, SimNonZoneEquipment, SimPlantLoops, SimElecCircuits);
    1834              : 
    1835      2854666 :         state.dataErrTracking->AskForPlantCheckOnAbort = true; // need to make a first pass through plant calcs before this check make sense
    1836      2854666 :         state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
    1837      2854666 :             state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
    1838              :     } else {
    1839      3160747 :         state.dataHVACMgr->FlowResolutionNeeded = false;
    1840      3160747 :         int IterAir = 0;
    1841      7268430 :         while ((SimAirLoops || SimZoneEquipment) && (IterAir <= MaxAir)) {
    1842      4107683 :             ++IterAir; // Increment the iteration counter
    1843              :             // Call AirflowNetwork simulation to calculate air flows and pressures
    1844      4107683 :             bool ResimulateAirZone = false;
    1845      4107683 :             if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    1846       256571 :                 state.afn->manage_balance(FirstHVACIteration, IterAir, ResimulateAirZone);
    1847              :             }
    1848      4107683 :             if (SimAirLoops) {
    1849      4107258 :                 SimAirServingZones::ManageAirLoops(state, FirstHVACIteration, SimAirLoops, SimZoneEquipment);
    1850      4107258 :                 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      4107683 :             if (state.dataHVACMgr->FlowResolutionNeeded) {
    1855        91499 :                 SimZoneEquipment = true;
    1856              :             }
    1857      4107683 :             if (SimZoneEquipment) {
    1858      3683086 :                 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       139291 :                     state.dataHVACMgr->FlowResolutionNeeded = true;
    1861              :                 } else {
    1862      3543795 :                     ResolveAirLoopFlowLimits(state);
    1863      3543795 :                     state.dataHVACMgr->FlowResolutionNeeded = false;
    1864              :                 }
    1865      3683086 :                 ZoneEquipmentManager::ManageZoneEquipment(state, FirstHVACIteration, SimZoneEquipment, SimAirLoops);
    1866      3683086 :                 SimElecCircuits = true; // If this was simulated there are possible electric changes that need to be simulated
    1867              :             }
    1868      4107683 :             state.dataHVACMgr->FlowMaxAvailAlreadyReset = false;
    1869              : 
    1870              :             //      IterAir = IterAir + 1   ! Increment the iteration counter
    1871      4107683 :             if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    1872       256571 :                 if (ResimulateAirZone) { // Need to make sure that SimAirLoop and SimZoneEquipment are simulated
    1873       104453 :                     SimAirLoops = true;  // at min three times using ONOFF fan with the AirflowNetwork model
    1874       104453 :                     SimZoneEquipment = true;
    1875              :                 }
    1876              :             }
    1877              :         }
    1878              : 
    1879      3160747 :         state.dataHVACMgr->RepIterAir += IterAir;
    1880              :         // Check to see if any components have been locked out. If so, SimAirLoops will be reset to TRUE.
    1881      3160747 :         ResolveLockoutFlags(state, SimAirLoops);
    1882              : 
    1883      3160747 :         if (SimNonZoneEquipment) {
    1884      2871304 :             NonZoneEquipmentManager::ManageNonZoneEquipment(state, FirstHVACIteration, SimNonZoneEquipment);
    1885      2871304 :             SimElecCircuits = true; // If this was simulated there are possible electric changes that need to be simulated
    1886              :         }
    1887              : 
    1888      3160747 :         if (SimElecCircuits) {
    1889      3139454 :             state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
    1890      3139454 :                 state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
    1891              :         }
    1892              : 
    1893      3160747 :         if (!SimPlantLoops) {
    1894              :             // check to see if any air side component may have requested plant resim
    1895       284707 :             if (PlantUtilities::AnyPlantLoopSidesNeedSim(state)) {
    1896        50887 :                 SimPlantLoops = true;
    1897              :             }
    1898              :         }
    1899              : 
    1900      3160747 :         if (SimPlantLoops) {
    1901      2926927 :             PlantManager::ManagePlantLoops(
    1902      2926927 :                 state, FirstHVACIteration, SimAirLoops, SimZoneEquipment, SimNonZoneEquipment, SimPlantLoops, SimElecCircuits);
    1903              :         }
    1904              : 
    1905      3160747 :         if (SimElecCircuits) {
    1906         1608 :             state.dataElectPwrSvcMgr->facilityElectricServiceObj->manageElectricPowerService(
    1907         1608 :                 state, FirstHVACIteration, state.dataHVACGlobal->SimElecCircuitsFlag, false);
    1908              :         }
    1909              :     }
    1910      6015413 : }
    1911              : 
    1912      2854666 : 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      7451923 :     for (int AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the primary air loops
    1928     19503440 :         for (int ZonesCooledIndex = 1; ZonesCooledIndex <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex).NumZonesCooled;
    1929              :              ++ZonesCooledIndex) { // loop over the zones cooled by this air loop
    1930     14906183 :             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     14906183 :             state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
    1933     14906183 :             state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMin;
    1934              :         }
    1935      4680115 :         for (int ZonesHeatedIndex = 1; ZonesHeatedIndex <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex).NumZonesHeated;
    1936              :              ++ZonesHeatedIndex) { // loop over the zones heated by this air loop
    1937        82858 :             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        82858 :             state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
    1940        82858 :             state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(TermInletNode).MassFlowRateMin;
    1941              :         }
    1942              :     }
    1943      2854666 : }
    1944              : 
    1945      3543795 : 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     10605813 :     for (int AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the primary air loops
    1963              : 
    1964      7062018 :         auto &AirToZoneNodeInfo = state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex);
    1965              : 
    1966     14150405 :         for (int SupplyIndex = 1; SupplyIndex <= AirToZoneNodeInfo.NumSupplyNodes; ++SupplyIndex) { // loop over the air loop supply outlets
    1967      7088387 :             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      6779838 :                 int SupplyNode = AirToZoneNodeInfo.AirLoopSupplyNodeNum(SupplyIndex);
    1971      6779838 :                 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      5647896 :                     if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
    1974      5647896 :                          state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) > DataConvergParams::HVACFlowRateToler * 0.01) {
    1975              :                         Real64 FlowRatio =
    1976       804753 :                             state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
    1977      1787077 :                         for (int ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
    1978       982324 :                             int TermInletNode = AirToZoneNodeInfo.TermUnitCoolInletNodes(ZonesCooledIndex);
    1979       982324 :                             state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
    1980       982324 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
    1981       982324 :                             state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
    1982       982324 :                                 min(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
    1983       982324 :                                     state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
    1984              :                         }
    1985              :                     }
    1986      5647896 :                     if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
    1987      5647896 :                          state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) < -DataConvergParams::HVACFlowRateToler * 0.01) {
    1988       339558 :                         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           40 :                             for (int ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
    1993           20 :                                 int TermInletNode = AirToZoneNodeInfo.TermUnitCoolInletNodes(ZonesCooledIndex);
    1994           20 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
    1995           20 :                                     state.dataLoopNodes->Node(TermInletNode).MassFlowRateMax;
    1996           20 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
    1997           20 :                                     state.dataLoopNodes->Node(SupplyNode).MassFlowRate / double(AirToZoneNodeInfo.NumZonesCooled);
    1998              :                             }
    1999              :                         } else {
    2000              :                             Real64 FlowRatio =
    2001       339538 :                                 state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
    2002       690762 :                             for (int ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
    2003       351224 :                                 int TermInletNode = AirToZoneNodeInfo.TermUnitCoolInletNodes(ZonesCooledIndex);
    2004       351224 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
    2005       351224 :                                     state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
    2006       351224 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
    2007       351224 :                                     max(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
    2008       351224 :                                         state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
    2009              :                             }
    2010              :                         }
    2011              :                     }
    2012              :                 }
    2013              :             }
    2014              :         }
    2015     14150405 :         for (int SupplyIndex = 1; SupplyIndex <= AirToZoneNodeInfo.NumSupplyNodes; ++SupplyIndex) { // loop over the air loop supply outlets
    2016      7088387 :             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        26369 :                 int SupplyNode = AirToZoneNodeInfo.AirLoopSupplyNodeNum(SupplyIndex);
    2020        26369 :                 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        20646 :                     if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
    2023        20646 :                          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        20646 :                     if ((state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint - state.dataLoopNodes->Node(SupplyNode).MassFlowRate -
    2036        20646 :                          state.dataAirLoop->AirLoopFlow(AirLoopIndex).BypassMassFlow) < -DataConvergParams::HVACFlowRateToler * 0.01) {
    2037            2 :                         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            2 :                                 state.dataLoopNodes->Node(SupplyNode).MassFlowRate / state.dataLoopNodes->Node(SupplyNode).MassFlowRateSetPoint;
    2049           14 :                             for (int ZonesHeatedIndex = 1; ZonesHeatedIndex <= AirToZoneNodeInfo.NumZonesHeated; ++ZonesHeatedIndex) {
    2050           12 :                                 int TermInletNode = AirToZoneNodeInfo.TermUnitHeatInletNodes(ZonesHeatedIndex);
    2051           12 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail =
    2052           12 :                                     state.dataLoopNodes->Node(TermInletNode).MassFlowRate * FlowRatio;
    2053           12 :                                 state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail =
    2054           12 :                                     max(state.dataLoopNodes->Node(TermInletNode).MassFlowRateMaxAvail,
    2055           12 :                                         state.dataLoopNodes->Node(TermInletNode).MassFlowRateMinAvail);
    2056              :                             }
    2057              :                         }
    2058              :                     }
    2059              :                 }
    2060              :             }
    2061              :         }
    2062              :     }
    2063      3543795 : }
    2064              : 
    2065      3160747 : 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      8974083 :     for (int AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the primary air loops
    2080      5813336 :         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      5813336 :         if (airLoopControlInfo.EconoActive &&
    2084       926836 :             (airLoopControlInfo.ReqstEconoLockoutWithCompressor || airLoopControlInfo.ReqstEconoLockoutWithHeating)) {
    2085        51298 :             airLoopControlInfo.EconoLockout = true;
    2086        51298 :             SimAir = true;
    2087              :         }
    2088              :     }
    2089      3160747 : }
    2090              : 
    2091      2854666 : 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      2854666 :     if (state.dataHVACGlobal->NumPrimaryAirSys == 0) {
    2104       951096 :         return;
    2105              :     }
    2106      6500575 :     for (auto &e : state.dataAirLoop->AirLoopControlInfo) {
    2107      4597005 :         e.NightVent = false;
    2108      4597005 :         e.LoopFlowRateSet = false;
    2109      1903570 :     }
    2110      6500575 :     for (auto &e : state.dataAirLoop->AirLoopFlow) {
    2111      4597005 :         e.ReqSupplyFrac = 1.0;
    2112      1903570 :     }
    2113              : }
    2114              : 
    2115         1672 : 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         1672 :     if (state.dataLoopNodes->NumOfNodes <= 0) {
    2126          162 :         return;
    2127              :     }
    2128              : 
    2129       139540 :     for (auto &e : state.dataLoopNodes->Node) {
    2130       138030 :         e.Temp = state.dataLoopNodes->DefaultNodeValues.Temp;
    2131       138030 :         e.TempMin = state.dataLoopNodes->DefaultNodeValues.TempMin;
    2132       138030 :         e.TempMax = state.dataLoopNodes->DefaultNodeValues.TempMax;
    2133       138030 :         e.TempSetPoint = state.dataLoopNodes->DefaultNodeValues.TempSetPoint;
    2134       138030 :         e.MassFlowRate = state.dataLoopNodes->DefaultNodeValues.MassFlowRate;
    2135       138030 :         e.MassFlowRateMin = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMin;
    2136       138030 :         e.MassFlowRateMax = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMax;
    2137       138030 :         e.MassFlowRateMinAvail = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMinAvail;
    2138       138030 :         e.MassFlowRateMaxAvail = state.dataLoopNodes->DefaultNodeValues.MassFlowRateMaxAvail;
    2139       138030 :         e.MassFlowRateSetPoint = state.dataLoopNodes->DefaultNodeValues.MassFlowRateSetPoint;
    2140       138030 :         e.Quality = state.dataLoopNodes->DefaultNodeValues.Quality;
    2141       138030 :         e.Press = state.dataLoopNodes->DefaultNodeValues.Press;
    2142       138030 :         e.Enthalpy = state.dataLoopNodes->DefaultNodeValues.Enthalpy;
    2143       138030 :         e.HumRat = state.dataLoopNodes->DefaultNodeValues.HumRat;
    2144       138030 :         e.HumRatMin = state.dataLoopNodes->DefaultNodeValues.HumRatMin;
    2145       138030 :         e.HumRatMax = state.dataLoopNodes->DefaultNodeValues.HumRatMax;
    2146       138030 :         e.HumRatSetPoint = state.dataLoopNodes->DefaultNodeValues.HumRatSetPoint;
    2147       138030 :         e.TempSetPointHi = state.dataLoopNodes->DefaultNodeValues.TempSetPointHi;
    2148       138030 :         e.TempSetPointLo = state.dataLoopNodes->DefaultNodeValues.TempSetPointLo;
    2149              :     }
    2150              : 
    2151         1510 :     if (allocated(state.dataLoopNodes->MoreNodeInfo)) {
    2152       139540 :         for (auto &e : state.dataLoopNodes->MoreNodeInfo) {
    2153       138030 :             e.WetBulbTemp = state.dataLoopNodes->DefaultNodeValues.Temp;
    2154       138030 :             e.RelHumidity = 0.0;
    2155       138030 :             e.ReportEnthalpy = state.dataLoopNodes->DefaultNodeValues.Enthalpy;
    2156       138030 :             e.VolFlowRateStdRho = 0.0;
    2157       138030 :             e.VolFlowRateCrntRho = 0.0;
    2158       138030 :             e.Density = 0.0;
    2159              :         }
    2160              :     }
    2161              : }
    2162              : 
    2163      3588830 : 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      3798450 :     for (ListNum = 1; ListNum <= state.dataHeatBal->NumOfZoneLists; ++ListNum) {
    2174       209620 :         state.dataHeatBal->ZoneListSNLoadHeatEnergy(ListNum) = 0.0;
    2175       209620 :         state.dataHeatBal->ZoneListSNLoadCoolEnergy(ListNum) = 0.0;
    2176       209620 :         state.dataHeatBal->ZoneListSNLoadHeatRate(ListNum) = 0.0;
    2177       209620 :         state.dataHeatBal->ZoneListSNLoadCoolRate(ListNum) = 0.0;
    2178              :     }
    2179              : 
    2180      3798450 :     for (ListNum = 1; ListNum <= state.dataHeatBal->NumOfZoneLists; ++ListNum) {
    2181       209620 :         auto &zoneList = state.dataHeatBal->ZoneList(ListNum);
    2182      1795678 :         for (ZoneNum = 1; ZoneNum <= zoneList.NumOfZones; ++ZoneNum) {
    2183      1586058 :             auto const &zoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneList.Zone(ZoneNum));
    2184      1586058 :             Mult = state.dataHeatBal->Zone(ZoneNum).Multiplier;
    2185      1586058 :             state.dataHeatBal->ZoneListSNLoadHeatEnergy(ListNum) += zoneSysEnergyDemand.airSysHeatEnergy * Mult;
    2186      1586058 :             state.dataHeatBal->ZoneListSNLoadCoolEnergy(ListNum) += zoneSysEnergyDemand.airSysCoolEnergy * Mult;
    2187      1586058 :             state.dataHeatBal->ZoneListSNLoadHeatRate(ListNum) += zoneSysEnergyDemand.airSysHeatRate * Mult;
    2188      1586058 :             state.dataHeatBal->ZoneListSNLoadCoolRate(ListNum) += zoneSysEnergyDemand.airSysCoolRate * Mult;
    2189              :         } // ZoneNum
    2190              :     } // ListNum
    2191              : 
    2192      3616154 :     for (GroupNum = 1; GroupNum <= state.dataHeatBal->NumOfZoneGroups; ++GroupNum) {
    2193        27324 :         auto &zoneGroup = state.dataHeatBal->ZoneGroup(GroupNum);
    2194        27324 :         Mult = zoneGroup.Multiplier;
    2195        27324 :         state.dataHeatBal->ZoneGroupSNLoadHeatEnergy(GroupNum) = state.dataHeatBal->ZoneListSNLoadHeatEnergy(zoneGroup.ZoneList) * Mult;
    2196        27324 :         state.dataHeatBal->ZoneGroupSNLoadCoolEnergy(GroupNum) = state.dataHeatBal->ZoneListSNLoadCoolEnergy(zoneGroup.ZoneList) * Mult;
    2197        27324 :         state.dataHeatBal->ZoneGroupSNLoadHeatRate(GroupNum) = state.dataHeatBal->ZoneListSNLoadHeatRate(zoneGroup.ZoneList) * Mult;
    2198        27324 :         state.dataHeatBal->ZoneGroupSNLoadCoolRate(GroupNum) = state.dataHeatBal->ZoneListSNLoadCoolRate(zoneGroup.ZoneList) * Mult;
    2199              :     } // GroupNum
    2200      3588830 : }
    2201              : 
    2202       623917 : 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       623917 :     Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    2221       623917 :     Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    2222              : 
    2223      3070621 :     for (auto &thisInfiltration : state.dataHeatBal->Infiltration) {
    2224              : 
    2225      2446704 :         int spaceNum = thisInfiltration.spaceIndex;
    2226      2446704 :         auto &thisSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum);
    2227      2446704 :         int NZ = thisInfiltration.ZonePtr;
    2228      2446704 :         auto const &thisZone = state.dataHeatBal->Zone(NZ);
    2229      2446704 :         ADSCorrectionFactor = 1.0;
    2230      2446704 :         if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
    2231              :             // CR7608 IF (TurnFansOn .AND. AirflowNetworkZoneFlag(NZ)) ADSCorrectionFactor=0
    2232         2692 :             if ((state.dataZoneEquip->ZoneEquipAvail(NZ) == Avail::Status::CycleOn ||
    2233         3826 :                  state.dataZoneEquip->ZoneEquipAvail(NZ) == Avail::Status::CycleOnZoneFansOnly) &&
    2234         1134 :                 state.afn->AirflowNetworkZoneFlag(NZ)) {
    2235         1134 :                 ADSCorrectionFactor = 0.0;
    2236              :             }
    2237              :         }
    2238              : 
    2239      2446704 :         CpAir = Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat);
    2240      2446704 :         thisInfiltration.InfilMdot = thisInfiltration.MCpI_temp / CpAir * ADSCorrectionFactor;
    2241      2446704 :         thisInfiltration.InfilMass = thisInfiltration.InfilMdot * TimeStepSysSec;
    2242              : 
    2243      2446704 :         if (thisSpaceHB.MAT > thisZone.OutDryBulbTemp) {
    2244              : 
    2245      1806724 :             thisInfiltration.InfilHeatLoss =
    2246      1806724 :                 thisInfiltration.MCpI_temp * (thisSpaceHB.MAT - thisZone.OutDryBulbTemp) * TimeStepSysSec * ADSCorrectionFactor;
    2247      1806724 :             thisInfiltration.InfilHeatGain = 0.0;
    2248              : 
    2249              :         } else {
    2250              : 
    2251       639980 :             thisInfiltration.InfilHeatGain =
    2252       639980 :                 thisInfiltration.MCpI_temp * (thisZone.OutDryBulbTemp - thisSpaceHB.MAT) * TimeStepSysSec * ADSCorrectionFactor;
    2253       639980 :             thisInfiltration.InfilHeatLoss = 0.0;
    2254              :         }
    2255              : 
    2256              :         // Report infiltration latent gains and losses
    2257      2446704 :         H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(thisSpaceHB.airHumRat, thisSpaceHB.MAT);
    2258      2446704 :         if (thisSpaceHB.airHumRat > state.dataEnvrn->OutHumRat) {
    2259              : 
    2260      1314457 :             thisInfiltration.InfilLatentLoss =
    2261      1314457 :                 thisInfiltration.InfilMdot * (thisSpaceHB.airHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap * TimeStepSysSec;
    2262      1314457 :             thisInfiltration.InfilLatentGain = 0.0;
    2263              : 
    2264              :         } else {
    2265              : 
    2266      1132247 :             thisInfiltration.InfilLatentGain =
    2267      1132247 :                 thisInfiltration.InfilMdot * (state.dataEnvrn->OutHumRat - thisSpaceHB.airHumRat) * H2OHtOfVap * TimeStepSysSec;
    2268      1132247 :             thisInfiltration.InfilLatentLoss = 0.0;
    2269              :         }
    2270              :         // Total infiltration losses and gains
    2271      2446704 :         TotalLoad =
    2272      2446704 :             thisInfiltration.InfilHeatGain + thisInfiltration.InfilLatentGain - thisInfiltration.InfilHeatLoss - thisInfiltration.InfilLatentLoss;
    2273      2446704 :         if (TotalLoad > 0) {
    2274       591298 :             thisInfiltration.InfilTotalGain = TotalLoad;
    2275       591298 :             thisInfiltration.InfilTotalLoss = 0.0;
    2276              :         } else {
    2277      1855406 :             thisInfiltration.InfilTotalGain = 0.0;
    2278      1855406 :             thisInfiltration.InfilTotalLoss = -TotalLoad;
    2279              :         }
    2280              :         // CR7751  second, calculate using indoor conditions for density property
    2281              :         Real64 const spAirDensity =
    2282      2446704 :             Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisSpaceHB.MAT, thisSpaceHB.airHumRatAvg, RoutineName);
    2283      2446704 :         thisInfiltration.InfilVdotCurDensity = thisInfiltration.InfilMdot / spAirDensity;
    2284      2446704 :         thisInfiltration.InfilVolumeCurDensity = thisInfiltration.InfilVdotCurDensity * TimeStepSysSec;
    2285              : 
    2286              :         // CR7751 third, calculate using standard dry air at nominal elevation
    2287      2446704 :         thisInfiltration.InfilVdotStdDensity = thisInfiltration.InfilMdot / state.dataEnvrn->StdRhoAir;
    2288      2446704 :         thisInfiltration.InfilVolumeStdDensity = thisInfiltration.InfilVdotStdDensity * TimeStepSysSec;
    2289              : 
    2290              :         // calculate using outdoor density
    2291              :         Real64 const outAirDensity =
    2292      2446704 :             Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZone.OutDryBulbTemp, state.dataEnvrn->OutHumRat, RoutineName);
    2293      2446704 :         thisInfiltration.InfilVdotOutDensity = thisInfiltration.InfilMdot / outAirDensity;
    2294              : 
    2295              :         // Air change rates
    2296      2446704 :         Real64 const vol = state.dataHeatBal->space(spaceNum).Volume;
    2297      2446704 :         if (vol > 0.0) {
    2298      2444664 :             Real64 secInHrOverVol = Constant::rSecsInHour / vol;
    2299      2444664 :             thisInfiltration.InfilAirChangeRateCurDensity = thisInfiltration.InfilVdotCurDensity * secInHrOverVol;
    2300      2444664 :             thisInfiltration.InfilAirChangeRateStdDensity = thisInfiltration.InfilVdotStdDensity * secInHrOverVol;
    2301      2444664 :             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       623917 :     }
    2309       623917 : }
    2310              : 
    2311       636404 : 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       636404 :     state.dataHeatBal->ZoneTotalExfiltrationHeatLoss = 0.0;
    2327       636404 :     state.dataHeatBal->ZoneTotalExhaustHeatLoss = 0.0;
    2328              : 
    2329       636404 :     if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    2330        13259 :         state.afn->report();
    2331              :     }
    2332              : 
    2333              :     // Reports zone exhaust loss by exhaust fans
    2334      4246738 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) { // Start of zone loads report variable update loop ...
    2335      3610334 :         auto &zone = state.dataHeatBal->Zone(zoneNum);
    2336      3610334 :         auto &znAirRpt = state.dataHeatBal->ZnAirRpt(zoneNum);
    2337      3610334 :         auto &znEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
    2338      3610334 :         reportAirHeatBal1(state, znAirRpt, znEquipConfig, zoneNum);
    2339              :     }
    2340       636404 :     if (state.dataHeatBal->doSpaceHeatBalance) {
    2341        12354 :         for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
    2342        10996 :             auto &spAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
    2343        10996 :             auto &spEquipConfig = state.dataZoneEquip->spaceEquipConfig(spaceNum);
    2344        10996 :             int zoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
    2345        10996 :             reportAirHeatBal1(state, spAirRpt, spEquipConfig, zoneNum, spaceNum);
    2346              :         }
    2347              :     }
    2348              : 
    2349              :     // Report results for SIMPLE option only
    2350       649663 :     if (!(state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution ||
    2351        13259 :           state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation)) {
    2352        12487 :         return;
    2353              :     }
    2354              : 
    2355       623917 :     ReportInfiltrations(state);
    2356              : 
    2357      4192630 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    2358      3568713 :         auto &znAirRpt = state.dataHeatBal->ZnAirRpt(zoneNum);
    2359      3568713 :         auto &znEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
    2360      3568713 :         auto &znHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum);
    2361      3568713 :         reportAirHeatBal2(state, znAirRpt, znEquipConfig, znHB, zoneNum);
    2362              :     }
    2363       623917 :     if (state.dataHeatBal->doSpaceHeatBalance) {
    2364        12354 :         for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
    2365        10996 :             auto &spAirRpt = state.dataHeatBal->spaceAirRpt(spaceNum);
    2366        10996 :             auto &spEquipConfig = state.dataZoneEquip->spaceEquipConfig(spaceNum);
    2367        10996 :             auto &spHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum);
    2368        10996 :             int zoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
    2369        10996 :             reportAirHeatBal2(state, spAirRpt, spEquipConfig, spHB, zoneNum, spaceNum);
    2370              :         }
    2371              :     }
    2372              : }
    2373              : 
    2374      3621330 : void reportAirHeatBal1(EnergyPlusData &state,
    2375              :                        DataHeatBalance::AirReportVars &szAirRpt,
    2376              :                        DataZoneEquipment::EquipConfiguration const &szEquipConfig,
    2377              :                        int const zoneNum,
    2378              :                        int const spaceNum)
    2379              : {
    2380      3621330 :     Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat); // Heat capacity of air (J/kg-C)
    2381      3621330 :     Real64 outDB = state.dataHeatBal->Zone(zoneNum).OutDryBulbTemp;
    2382      3621330 :     Real64 H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(state.dataEnvrn->OutHumRat, outDB); // Heat of vaporization of air
    2383      3621330 :     Real64 ADSCorrectionFactor = 1.0;
    2384      3621330 :     if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
    2385         2692 :         if ((state.dataZoneEquip->ZoneEquipAvail(zoneNum) == Avail::Status::CycleOn ||
    2386         3826 :              state.dataZoneEquip->ZoneEquipAvail(zoneNum) == Avail::Status::CycleOnZoneFansOnly) &&
    2387         1134 :             state.afn->AirflowNetworkZoneFlag(zoneNum)) {
    2388         1134 :             ADSCorrectionFactor = 0.0;
    2389              :         }
    2390              :     }
    2391              : 
    2392      3621330 :     szAirRpt.ExhTotalLoss = 0;
    2393      3621330 :     szAirRpt.ExhSensiLoss = 0;
    2394              : 
    2395     41682205 :     for (int FanNum = 1; FanNum <= (int)state.dataFans->fans.size(); ++FanNum) {
    2396     38060875 :         auto const *thisFan = state.dataFans->fans(FanNum);
    2397              :         //  Add reportable vars
    2398     38060875 :         if (thisFan->type == HVAC::FanType::Exhaust) {
    2399      7341209 :             for (int ExhNum = 1; ExhNum <= szEquipConfig.NumExhaustNodes; ExhNum++) {
    2400      2293991 :                 if (thisFan->inletNodeNum == szEquipConfig.ExhaustNode(ExhNum)) {
    2401        67304 :                     szAirRpt.ExhTotalLoss +=
    2402        67304 :                         thisFan->outletAirMassFlowRate * (thisFan->outletAirEnthalpy - state.dataEnvrn->OutEnthalpy) * ADSCorrectionFactor;
    2403        67304 :                     szAirRpt.ExhSensiLoss += thisFan->outletAirMassFlowRate * CpAir * (thisFan->outletAirTemp - outDB) * ADSCorrectionFactor;
    2404        67304 :                     break;
    2405              :                 }
    2406              :             }
    2407              :         }
    2408              :     }
    2409              : 
    2410      3621330 :     szAirRpt.ExhLatentLoss = szAirRpt.ExhTotalLoss - szAirRpt.ExhSensiLoss;
    2411      3621330 : }
    2412      3579709 : 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      3579709 :     Real64 ADSCorrectionFactor = 1.0;
    2423              : 
    2424      3579709 :     if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
    2425              :         // CR7608 IF (TurnFansOn .AND. AirflowNetworkZoneFlag(zoneNum)) ADSCorrectionFactor=0
    2426         2692 :         if ((state.dataZoneEquip->ZoneEquipAvail(zoneNum) == Avail::Status::CycleOn ||
    2427         3826 :              state.dataZoneEquip->ZoneEquipAvail(zoneNum) == Avail::Status::CycleOnZoneFansOnly) &&
    2428         1134 :             state.afn->AirflowNetworkZoneFlag(zoneNum)) {
    2429         1134 :             ADSCorrectionFactor = 0.0;
    2430              :         }
    2431              :     }
    2432              : 
    2433      3579709 :     Real64 const outDryBulb = state.dataHeatBal->Zone(zoneNum).OutDryBulbTemp;
    2434      3579709 :     if (szHeatBal.MAT > outDryBulb) {
    2435              : 
    2436      2682281 :         szAirRpt.InfilHeatLoss = szHeatBal.MCPI * (szHeatBal.MAT - outDryBulb) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2437      2682281 :         szAirRpt.InfilHeatGain = 0.0;
    2438              : 
    2439              :     } else {
    2440              : 
    2441       897428 :         szAirRpt.InfilHeatGain = szHeatBal.MCPI * (outDryBulb - szHeatBal.MAT) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2442       897428 :         szAirRpt.InfilHeatLoss = 0.0;
    2443              :     }
    2444              :     // Report infiltration latent gains and losses
    2445      3579709 :     Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat);                 // Heat capacity of air (J/kg-C)
    2446      3579709 :     Real64 H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(szHeatBal.airHumRat, szHeatBal.MAT); // Heat of vaporization of air
    2447      3579709 :     if (szHeatBal.airHumRat > state.dataEnvrn->OutHumRat) {
    2448              : 
    2449      1915185 :         szAirRpt.InfilLatentLoss = szHeatBal.MCPI / CpAir * (szHeatBal.airHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap *
    2450      1915185 :                                    state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2451      1915185 :         szAirRpt.InfilLatentGain = 0.0;
    2452              : 
    2453              :     } else {
    2454              : 
    2455      1664524 :         szAirRpt.InfilLatentGain = szHeatBal.MCPI / CpAir * (state.dataEnvrn->OutHumRat - szHeatBal.airHumRat) * H2OHtOfVap *
    2456      1664524 :                                    state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2457      1664524 :         szAirRpt.InfilLatentLoss = 0.0;
    2458              :     }
    2459              :     // Total infiltration losses and gains
    2460      3579709 :     Real64 TotalLoad = szAirRpt.InfilHeatGain + szAirRpt.InfilLatentGain - szAirRpt.InfilHeatLoss - szAirRpt.InfilLatentLoss;
    2461      3579709 :     if (TotalLoad > 0) {
    2462       589671 :         szAirRpt.InfilTotalGain = TotalLoad * ADSCorrectionFactor;
    2463       589671 :         szAirRpt.InfilTotalLoss = 0.0;
    2464              :     } else {
    2465      2990038 :         szAirRpt.InfilTotalGain = 0.0;
    2466      2990038 :         szAirRpt.InfilTotalLoss = -TotalLoad * ADSCorrectionFactor;
    2467              :     }
    2468              : 
    2469              :     // first calculate mass flows using outside air heat capacity for consistency with input to heat balance
    2470      3579709 :     szAirRpt.InfilMdot = (szHeatBal.MCPI / CpAir) * ADSCorrectionFactor;
    2471      3579709 :     szAirRpt.InfilMass = szAirRpt.InfilMdot * state.dataHVACGlobal->TimeStepSysSec;
    2472      3579709 :     szAirRpt.VentilMdot = (szHeatBal.MCPV / CpAir) * ADSCorrectionFactor;
    2473      3579709 :     szAirRpt.VentilMass = szAirRpt.VentilMdot * state.dataHVACGlobal->TimeStepSysSec;
    2474              : 
    2475              :     // CR7751  second, calculate using indoor conditions for density property
    2476              :     Real64 const szAirDensity =
    2477      3579709 :         Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, szHeatBal.MAT, szHeatBal.airHumRatAvg, RoutineName);
    2478      3579709 :     szAirRpt.InfilVdotCurDensity = szAirRpt.InfilMdot / szAirDensity;
    2479      3579709 :     szAirRpt.InfilVolumeCurDensity = szAirRpt.InfilVdotCurDensity * state.dataHVACGlobal->TimeStepSysSec;
    2480      3579709 :     szAirRpt.VentilVdotCurDensity = szAirRpt.VentilMdot / szAirDensity;
    2481      3579709 :     szAirRpt.VentilVolumeCurDensity = szAirRpt.VentilVdotCurDensity * state.dataHVACGlobal->TimeStepSysSec;
    2482              : 
    2483              :     // CR7751 third, calculate using standard dry air at nominal elevation
    2484      3579709 :     szAirRpt.InfilVdotStdDensity = szAirRpt.InfilMdot / state.dataEnvrn->StdRhoAir;
    2485      3579709 :     szAirRpt.InfilVolumeStdDensity = szAirRpt.InfilVdotStdDensity * state.dataHVACGlobal->TimeStepSysSec;
    2486      3579709 :     szAirRpt.VentilVdotStdDensity = szAirRpt.VentilMdot / state.dataEnvrn->StdRhoAir;
    2487      3579709 :     szAirRpt.VentilVolumeStdDensity = szAirRpt.VentilVdotStdDensity * state.dataHVACGlobal->TimeStepSysSec;
    2488              : 
    2489              :     // Calculate using outdoor air density
    2490              :     Real64 const outAirDensity =
    2491      3579709 :         Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, outDryBulb, state.dataEnvrn->OutHumRat, RoutineName);
    2492      3579709 :     szAirRpt.InfilVdotOutDensity = szAirRpt.InfilMdot / outAirDensity;
    2493      3579709 :     szAirRpt.VentilVdotOutDensity = szAirRpt.VentilMdot / outAirDensity;
    2494              : 
    2495              :     // calculate air change rates
    2496      3579709 :     Real64 const szVolume = (spaceNum == 0) ? state.dataHeatBal->Zone(zoneNum).Volume : state.dataHeatBal->space(spaceNum).Volume;
    2497      3579709 :     if (szVolume > 0.0) {
    2498      3578997 :         Real64 secInHrOverVol = Constant::rSecsInHour / szVolume;
    2499      3578997 :         szAirRpt.InfilAirChangeRateCurDensity = szAirRpt.InfilVdotCurDensity * secInHrOverVol;
    2500      3578997 :         szAirRpt.InfilAirChangeRateStdDensity = szAirRpt.InfilVdotStdDensity * secInHrOverVol;
    2501      3578997 :         szAirRpt.InfilAirChangeRateOutDensity = szAirRpt.InfilVdotOutDensity * secInHrOverVol;
    2502      3578997 :         szAirRpt.VentilAirChangeRateCurDensity = szAirRpt.VentilVdotCurDensity * secInHrOverVol;
    2503      3578997 :         szAirRpt.VentilAirChangeRateStdDensity = szAirRpt.VentilVdotStdDensity * secInHrOverVol;
    2504      3578997 :         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      3579709 :     szAirRpt.VentilAirTemp = 0.0;
    2517      3579709 :     szAirRpt.VentilHeatLoss = 0.0;
    2518      3579709 :     szAirRpt.VentilHeatGain = 0.0;
    2519      3579709 :     int ventCount = 0;             // Number of ventilation object per zone or space
    2520      3579709 :     Real64 VentZoneMassflow = 0.0; // Total mass flow rate per zone
    2521      3579709 :     Real64 VentZoneAirTemp = 0.0;  // Average Zone inlet temperature
    2522              : 
    2523      5437870 :     for (int VentNum = 1; VentNum <= state.dataHeatBal->TotVentilation; ++VentNum) {
    2524      1858161 :         auto const &ventilation = state.dataHeatBal->Ventilation(VentNum);
    2525      1858161 :         if (((spaceNum == 0) && (ventilation.ZonePtr == zoneNum)) || ((spaceNum > 0) && (spaceNum == ventilation.spaceIndex))) {
    2526        43712 :             if (ADSCorrectionFactor > 0) {
    2527        42578 :                 szAirRpt.VentilAirTemp += ventilation.AirTemp * ventilation.MCP;
    2528        42578 :                 VentZoneMassflow += ventilation.MCP;
    2529        42578 :                 VentZoneAirTemp += ventilation.AirTemp;
    2530              :             } else {
    2531         1134 :                 szAirRpt.VentilAirTemp = outDryBulb;
    2532              :             }
    2533              :             // Break the ventilation load into heat gain and loss components
    2534        43712 :             if (szHeatBal.MAT > ventilation.AirTemp) {
    2535        33694 :                 szAirRpt.VentilHeatLoss +=
    2536        33694 :                     ventilation.MCP * (szHeatBal.MAT - ventilation.AirTemp) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2537              :             } else {
    2538        10018 :                 szAirRpt.VentilHeatGain +=
    2539        10018 :                     ventilation.MCP * (ventilation.AirTemp - szHeatBal.MAT) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2540              :             }
    2541              : 
    2542        43712 :             ++ventCount;
    2543        43712 :             if (ventCount > 1) {
    2544          968 :                 continue;
    2545              :             }
    2546              : 
    2547              :             // Report ventilation latent gains and losses
    2548        42744 :             H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(szHeatBal.airHumRat, szHeatBal.MAT);
    2549        42744 :             if (szHeatBal.airHumRat > state.dataEnvrn->OutHumRat) {
    2550        33507 :                 szAirRpt.VentilLatentLoss =
    2551        33507 :                     szAirRpt.VentilMdot * (szHeatBal.airHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap * state.dataHVACGlobal->TimeStepSysSec;
    2552        33507 :                 szAirRpt.VentilLatentGain = 0.0;
    2553              :             } else {
    2554         9237 :                 szAirRpt.VentilLatentGain =
    2555         9237 :                     szAirRpt.VentilMdot * (state.dataEnvrn->OutHumRat - szHeatBal.airHumRat) * H2OHtOfVap * state.dataHVACGlobal->TimeStepSysSec;
    2556         9237 :                 szAirRpt.VentilLatentLoss = 0.0;
    2557              :             }
    2558              :             // Total ventilation losses and gains
    2559        42744 :             TotalLoad = szAirRpt.VentilHeatGain + szAirRpt.VentilLatentGain - szAirRpt.VentilHeatLoss - szAirRpt.VentilLatentLoss;
    2560        42744 :             if (TotalLoad > 0) {
    2561         1036 :                 szAirRpt.VentilTotalGain = TotalLoad * ADSCorrectionFactor;
    2562         1036 :                 szAirRpt.VentilTotalLoss = 0.0;
    2563              :             } else {
    2564        41708 :                 szAirRpt.VentilTotalGain = 0.0;
    2565        41708 :                 szAirRpt.VentilTotalLoss = -TotalLoad * ADSCorrectionFactor;
    2566              :             }
    2567              :         }
    2568              :     }
    2569              : 
    2570      3579709 :     if (ADSCorrectionFactor > 0 && ventCount > 1 && VentZoneMassflow > 0.0) {
    2571          357 :         szAirRpt.VentilAirTemp /= VentZoneMassflow;
    2572      3579352 :     } else if (ADSCorrectionFactor > 0 && ventCount == 1) {
    2573        40642 :         szAirRpt.VentilAirTemp = VentZoneAirTemp;
    2574              :     } else { // Just in case
    2575      3538710 :         szAirRpt.VentilAirTemp = outDryBulb;
    2576              :     }
    2577              : 
    2578              :     // Report mixing sensible and latent loads
    2579      3579709 :     szAirRpt.MixSenLoad = 0.0; // Initialize arrays to zero before starting to sum
    2580      3579709 :     szAirRpt.MixLatLoad = 0.0;
    2581      3579709 :     szAirRpt.MixVolume = 0.0;         // zero reported volume prior to summations below
    2582      3579709 :     szAirRpt.MixVdotCurDensity = 0.0; // zero reported volume flow rate prior to summations below
    2583      3579709 :     szAirRpt.MixVdotStdDensity = 0.0; // zero reported volume flow rate prior to summations below
    2584      3579709 :     szAirRpt.MixMass = 0.0;           // ! zero reported mass prior to summations below
    2585      3579709 :     szAirRpt.MixMdot = 0.0;           // ! zero reported mass flow rate prior to summations below
    2586              :     //    MixingLoad = 0.0d0
    2587              : 
    2588      5685523 :     for (int MixNum = 1; MixNum <= state.dataHeatBal->TotMixing; ++MixNum) {
    2589      2105814 :         auto &mixing = state.dataHeatBal->Mixing(MixNum);
    2590      2105814 :         if (mixing.ReportFlag && (((spaceNum == 0) && (mixing.ZonePtr == zoneNum)) || ((spaceNum > 0) && (spaceNum == mixing.spaceIndex)))) {
    2591        53538 :             Real64 const fromMAT = (mixing.fromSpaceIndex == 0) ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(mixing.FromZone).MAT
    2592        27258 :                                                                 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(mixing.fromSpaceIndex).MAT;
    2593        53538 :             Real64 const fromHumRat = (mixing.fromSpaceIndex == 0)
    2594        53538 :                                           ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(mixing.FromZone).airHumRat
    2595        27258 :                                           : 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       107076 :             Real64 const AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(
    2601       160614 :                 state, state.dataEnvrn->OutBaroPress, (szHeatBal.MAT + fromMAT) / 2.0, (szHeatBal.airHumRat + fromHumRat) / 2.0, std::string());
    2602        53538 :             CpAir = Psychrometrics::PsyCpAirFnW((szHeatBal.airHumRat + fromHumRat) / 2.0);
    2603        53538 :             szAirRpt.MixVolume += mixing.DesiredAirFlowRate * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2604        53538 :             szAirRpt.MixVdotCurDensity += mixing.DesiredAirFlowRate * ADSCorrectionFactor;
    2605        53538 :             szAirRpt.MixMass += mixing.DesiredAirFlowRate * AirDensity * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2606        53538 :             szAirRpt.MixMdot += mixing.DesiredAirFlowRate * AirDensity * ADSCorrectionFactor;
    2607        53538 :             szAirRpt.MixVdotStdDensity += mixing.DesiredAirFlowRate * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
    2608        53538 :             szAirRpt.MixSenLoad += mixing.DesiredAirFlowRate * AirDensity * CpAir * (szHeatBal.MAT - fromMAT);
    2609        53538 :             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        53538 :             szAirRpt.MixLatLoad += mixing.DesiredAirFlowRate * AirDensity * (szHeatBal.airHumRat - fromHumRat) * H2OHtOfVap;
    2613              :         }
    2614              :     }
    2615              : 
    2616      3608517 :     for (int MixNum = 1; MixNum <= state.dataHeatBal->TotCrossMixing; ++MixNum) {
    2617        28808 :         auto &crossMixing = state.dataHeatBal->CrossMixing(MixNum);
    2618        28808 :         if (crossMixing.ReportFlag &&
    2619        24140 :             ((((spaceNum == 0) && (crossMixing.ZonePtr == zoneNum)) || (spaceNum > 0) && (spaceNum == crossMixing.spaceIndex)))) {
    2620         4093 :             Real64 const fromMAT = (crossMixing.fromSpaceIndex == 0)
    2621         4093 :                                        ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(crossMixing.FromZone).MAT
    2622         4093 :                                        : state.dataZoneTempPredictorCorrector->spaceHeatBalance(crossMixing.fromSpaceIndex).MAT;
    2623         4093 :             Real64 const fromHumRat = (crossMixing.fromSpaceIndex == 0)
    2624         4093 :                                           ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(crossMixing.FromZone).airHumRat
    2625         4093 :                                           : 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         8186 :             Real64 const AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(
    2630        12279 :                 state, state.dataEnvrn->OutBaroPress, (szHeatBal.MAT + fromMAT) / 2.0, (szHeatBal.airHumRat + fromHumRat) / 2.0, std::string());
    2631         4093 :             CpAir = Psychrometrics::PsyCpAirFnW((szHeatBal.airHumRat + fromHumRat) / 2.0);
    2632         4093 :             szAirRpt.MixVolume += crossMixing.DesiredAirFlowRate * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2633         4093 :             szAirRpt.MixVdotCurDensity += crossMixing.DesiredAirFlowRate * ADSCorrectionFactor;
    2634         4093 :             szAirRpt.MixMass += crossMixing.DesiredAirFlowRate * AirDensity * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2635         4093 :             szAirRpt.MixMdot += crossMixing.DesiredAirFlowRate * AirDensity * ADSCorrectionFactor;
    2636         4093 :             szAirRpt.MixVdotStdDensity += crossMixing.DesiredAirFlowRate * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
    2637         4093 :             szAirRpt.MixSenLoad += crossMixing.DesiredAirFlowRate * AirDensity * CpAir * (szHeatBal.MAT - fromMAT);
    2638         4093 :             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         4093 :             szAirRpt.MixLatLoad += crossMixing.DesiredAirFlowRate * AirDensity * (szHeatBal.airHumRat - fromHumRat) * H2OHtOfVap;
    2642              :         }
    2643        28808 :         if (crossMixing.ReportFlag &&
    2644        24140 :             (((spaceNum == 0) && (crossMixing.FromZone == zoneNum)) || ((spaceNum > 0) && (spaceNum == crossMixing.fromSpaceIndex)))) {
    2645         4093 :             Real64 const mixingMAT = (crossMixing.spaceIndex == 0)
    2646         4093 :                                          ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(crossMixing.ZonePtr).MAT
    2647         4093 :                                          : state.dataZoneTempPredictorCorrector->spaceHeatBalance(crossMixing.spaceIndex).MAT;
    2648         4093 :             Real64 const mixingHumRat = (crossMixing.fromSpaceIndex == 0)
    2649         4093 :                                             ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(crossMixing.ZonePtr).airHumRat
    2650         4093 :                                             : state.dataZoneTempPredictorCorrector->spaceHeatBalance(crossMixing.spaceIndex).airHumRat;
    2651         8186 :             Real64 const AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(
    2652        12279 :                 state, state.dataEnvrn->OutBaroPress, (szHeatBal.MAT + mixingMAT) / 2.0, (szHeatBal.airHumRat + mixingHumRat) / 2.0, std::string());
    2653         4093 :             CpAir = Psychrometrics::PsyCpAirFnW((szHeatBal.airHumRat + mixingHumRat) / 2.0);
    2654         4093 :             szAirRpt.MixVolume += crossMixing.DesiredAirFlowRate * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2655         4093 :             szAirRpt.MixVdotCurDensity += crossMixing.DesiredAirFlowRate * ADSCorrectionFactor;
    2656         4093 :             szAirRpt.MixMass += crossMixing.DesiredAirFlowRate * AirDensity * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2657         4093 :             szAirRpt.MixMdot += crossMixing.DesiredAirFlowRate * AirDensity * ADSCorrectionFactor;
    2658         4093 :             szAirRpt.MixVdotStdDensity += crossMixing.DesiredAirFlowRate * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
    2659         4093 :             szAirRpt.MixSenLoad += crossMixing.DesiredAirFlowRate * AirDensity * CpAir * (szHeatBal.MAT - mixingMAT);
    2660         4093 :             H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb((szHeatBal.airHumRat + mixingHumRat) / 2.0, (szHeatBal.MAT + mixingMAT) / 2.0);
    2661         4093 :             szAirRpt.MixLatLoad += crossMixing.DesiredAirFlowRate * AirDensity * (szHeatBal.airHumRat - mixingHumRat) * H2OHtOfVap;
    2662              :         }
    2663              :     }
    2664              : 
    2665      3579709 :     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        11998 :         auto &refDoorMixing = state.dataHeatBal->RefDoorMixing(zoneNum);
    2671        11998 :         if (refDoorMixing.RefDoorMixFlag) { // .TRUE. for both zoneA and zoneB
    2672         4285 :             if (((spaceNum == 0) && (refDoorMixing.ZonePtr == zoneNum)) || ((spaceNum > 0) && (spaceNum == refDoorMixing.spaceIndex))) {
    2673         5142 :                 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         2571 :                     if (refDoorMixing.VolRefDoorFlowRate(j) > 0.0) {
    2677              :                         // int ZoneB = refDoorMixing.MateZonePtr(j);
    2678              :                         // auto const &zoneBHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneB);
    2679         1440 :                         Real64 const szBMAT = (refDoorMixing.fromSpaceIndex == 0)
    2680         1440 :                                                   ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(refDoorMixing.MateZonePtr(j)).MAT
    2681         1440 :                                                   : state.dataZoneTempPredictorCorrector->spaceHeatBalance(refDoorMixing.fromSpaceIndex).MAT;
    2682         1440 :                         Real64 const szBHumRat = (refDoorMixing.fromSpaceIndex == 0)
    2683         1440 :                                                      ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(refDoorMixing.MateZonePtr(j)).airHumRat
    2684         1440 :                                                      : state.dataZoneTempPredictorCorrector->spaceHeatBalance(refDoorMixing.fromSpaceIndex).airHumRat;
    2685         2880 :                         Real64 const AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state,
    2686         1440 :                                                                                     state.dataEnvrn->OutBaroPress,
    2687         1440 :                                                                                     (szHeatBal.MAT + szBMAT) / 2.0,
    2688         1440 :                                                                                     (szHeatBal.airHumRat + szBHumRat) / 2.0,
    2689         2880 :                                                                                     std::string());
    2690         1440 :                         CpAir = Psychrometrics::PsyCpAirFnW((szHeatBal.airHumRat + szBHumRat) / 2.0);
    2691         1440 :                         H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb((szHeatBal.airHumRat + szBHumRat) / 2.0, (szHeatBal.MAT + szBMAT) / 2.0);
    2692         1440 :                         szAirRpt.MixVolume += refDoorMixing.VolRefDoorFlowRate(j) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2693         1440 :                         szAirRpt.MixVdotCurDensity += refDoorMixing.VolRefDoorFlowRate(j) * ADSCorrectionFactor;
    2694         1440 :                         szAirRpt.MixMass +=
    2695         1440 :                             refDoorMixing.VolRefDoorFlowRate(j) * AirDensity * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2696         1440 :                         szAirRpt.MixMdot += refDoorMixing.VolRefDoorFlowRate(j) * AirDensity * ADSCorrectionFactor;
    2697         1440 :                         szAirRpt.MixVdotStdDensity +=
    2698         1440 :                             refDoorMixing.VolRefDoorFlowRate(j) * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
    2699         1440 :                         szAirRpt.MixSenLoad += refDoorMixing.VolRefDoorFlowRate(j) * AirDensity * CpAir * (szHeatBal.MAT - szBMAT);
    2700         1440 :                         szAirRpt.MixLatLoad += refDoorMixing.VolRefDoorFlowRate(j) * AirDensity * (szHeatBal.airHumRat - szBHumRat) * H2OHtOfVap;
    2701              :                     } // flow > 0
    2702              :                 } // J-1, numref connections
    2703              :             } // zone A (zoneptr = zoneNum)
    2704        23139 :             for (int ZoneA = 1; ZoneA <= (zoneNum - 1); ++ZoneA) {
    2705        18854 :                 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        18854 :                 if (refDoorMixingA.RefDoorMixFlag) {
    2709        14569 :                     for (int j = 1; j <= refDoorMixingA.NumRefDoorConnections; ++j) {
    2710         9427 :                         if (((spaceNum == 0) && (refDoorMixingA.MateZonePtr(j) == zoneNum)) ||
    2711         3428 :                             ((spaceNum == 0) && (refDoorMixingA.fromSpaceIndex == spaceNum))) {
    2712         2571 :                             if (refDoorMixingA.VolRefDoorFlowRate(j) > 0.0) {
    2713              :                                 // auto const &zoneAHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneA);
    2714         1440 :                                 Real64 const szAMAT = (refDoorMixingA.spaceIndex == 0)
    2715         1440 :                                                           ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(refDoorMixingA.ZonePtr).MAT
    2716         1440 :                                                           : state.dataZoneTempPredictorCorrector->spaceHeatBalance(refDoorMixingA.spaceIndex).MAT;
    2717              :                                 Real64 const szAHumRat =
    2718         1440 :                                     (refDoorMixingA.spaceIndex == 0)
    2719         1440 :                                         ? state.dataZoneTempPredictorCorrector->zoneHeatBalance(refDoorMixingA.ZonePtr).airHumRat
    2720         1440 :                                         : state.dataZoneTempPredictorCorrector->spaceHeatBalance(refDoorMixingA.spaceIndex).airHumRat;
    2721         2880 :                                 Real64 const AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state,
    2722         1440 :                                                                                             state.dataEnvrn->OutBaroPress,
    2723         1440 :                                                                                             (szHeatBal.MAT + szAMAT) / 2.0,
    2724         1440 :                                                                                             (szHeatBal.airHumRat + szAHumRat) / 2.0,
    2725         2880 :                                                                                             std::string());
    2726         1440 :                                 CpAir = Psychrometrics::PsyCpAirFnW((szHeatBal.airHumRat + szAHumRat) / 2.0);
    2727         1440 :                                 H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb((szHeatBal.airHumRat + szAHumRat) / 2.0, (szHeatBal.MAT + szAMAT) / 2.0);
    2728         1440 :                                 szAirRpt.MixVolume +=
    2729         1440 :                                     refDoorMixingA.VolRefDoorFlowRate(j) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2730         1440 :                                 szAirRpt.MixVdotCurDensity += refDoorMixingA.VolRefDoorFlowRate(j) * ADSCorrectionFactor;
    2731         1440 :                                 szAirRpt.MixMass +=
    2732         1440 :                                     refDoorMixingA.VolRefDoorFlowRate(j) * AirDensity * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2733         1440 :                                 szAirRpt.MixMdot += refDoorMixingA.VolRefDoorFlowRate(j) * AirDensity * ADSCorrectionFactor;
    2734         1440 :                                 szAirRpt.MixVdotStdDensity +=
    2735         1440 :                                     refDoorMixingA.VolRefDoorFlowRate(j) * (AirDensity / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
    2736         1440 :                                 szAirRpt.MixSenLoad += refDoorMixingA.VolRefDoorFlowRate(j) * AirDensity * CpAir * (szHeatBal.MAT - szAMAT);
    2737         1440 :                                 szAirRpt.MixLatLoad +=
    2738         1440 :                                     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      3579709 :     if (szAirRpt.MixSenLoad > 0.0) {
    2750        20902 :         szAirRpt.MixHeatLoss = szAirRpt.MixSenLoad * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2751        20902 :         szAirRpt.MixHeatGain = 0.0;
    2752              :     } else {
    2753      3558807 :         szAirRpt.MixHeatLoss = 0.0;
    2754      3558807 :         szAirRpt.MixHeatGain = -szAirRpt.MixSenLoad * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2755              :     }
    2756              :     // Report mixing latent loads
    2757              :     //    MixingLoad(zoneNum) = szAirRpt.MixLatLoad(zoneNum)
    2758      3579709 :     if (szAirRpt.MixLatLoad > 0.0) {
    2759        21316 :         szAirRpt.MixLatentLoss = szAirRpt.MixLatLoad * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2760        21316 :         szAirRpt.MixLatentGain = 0.0;
    2761              :     } else {
    2762      3558393 :         szAirRpt.MixLatentLoss = 0.0;
    2763      3558393 :         szAirRpt.MixLatentGain = -szAirRpt.MixLatLoad * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2764              :     }
    2765              :     // Total Mixing losses and gains
    2766      3579709 :     TotalLoad = szAirRpt.MixHeatGain + szAirRpt.MixLatentGain - szAirRpt.MixHeatLoss - szAirRpt.MixLatentLoss;
    2767      3579709 :     if (TotalLoad > 0) {
    2768         9843 :         szAirRpt.MixTotalGain = TotalLoad * ADSCorrectionFactor;
    2769         9843 :         szAirRpt.MixTotalLoss = 0.0;
    2770              :     } else {
    2771      3569866 :         szAirRpt.MixTotalGain = 0.0;
    2772      3569866 :         szAirRpt.MixTotalLoss = -TotalLoad * ADSCorrectionFactor;
    2773              :     }
    2774              : 
    2775              :     // Reporting combined outdoor air flows
    2776      3585088 :     for (int j = 1; j <= state.dataHeatBal->TotZoneAirBalance; ++j) {
    2777        10758 :         if (state.dataHeatBal->ZoneAirBalance(j).BalanceMethod == DataHeatBalance::AirBalance::Quadrature &&
    2778         5379 :             zoneNum == state.dataHeatBal->ZoneAirBalance(j).ZonePtr) {
    2779         1793 :             if (szHeatBal.MAT > outDryBulb) {
    2780         1652 :                 szAirRpt.OABalanceHeatLoss =
    2781         1652 :                     szHeatBal.MDotCPOA * (szHeatBal.MAT - outDryBulb) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2782         1652 :                 szAirRpt.OABalanceHeatGain = 0.0;
    2783              :             } else {
    2784          141 :                 szAirRpt.OABalanceHeatLoss = 0.0;
    2785          141 :                 szAirRpt.OABalanceHeatGain =
    2786          141 :                     -szHeatBal.MDotCPOA * (szHeatBal.MAT - outDryBulb) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2787              :             }
    2788         1793 :             H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(state.dataEnvrn->OutHumRat, outDryBulb);
    2789         1793 :             if (szHeatBal.airHumRat > state.dataEnvrn->OutHumRat) {
    2790          220 :                 szAirRpt.OABalanceLatentLoss = szHeatBal.MDotOA * (szHeatBal.airHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap *
    2791          220 :                                                state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2792          220 :                 szAirRpt.OABalanceLatentGain = 0.0;
    2793              :             } else {
    2794         1573 :                 szAirRpt.OABalanceLatentGain = szHeatBal.MDotOA * (state.dataEnvrn->OutHumRat - szHeatBal.airHumRat) * H2OHtOfVap *
    2795         1573 :                                                state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2796         1573 :                 szAirRpt.OABalanceLatentLoss = 0.0;
    2797              :             }
    2798              :             // Total ventilation losses and gains
    2799         1793 :             TotalLoad = szAirRpt.OABalanceHeatGain + szAirRpt.OABalanceLatentGain - szAirRpt.OABalanceHeatLoss - szAirRpt.OABalanceLatentLoss;
    2800         1793 :             if (TotalLoad > 0) {
    2801          162 :                 szAirRpt.OABalanceTotalGain = TotalLoad * ADSCorrectionFactor;
    2802          162 :                 szAirRpt.OABalanceTotalLoss = 0.0;
    2803              :             } else {
    2804         1631 :                 szAirRpt.OABalanceTotalGain = 0.0;
    2805         1631 :                 szAirRpt.OABalanceTotalLoss = -TotalLoad * ADSCorrectionFactor;
    2806              :             }
    2807         1793 :             szAirRpt.OABalanceMass = (szHeatBal.MDotOA) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2808         1793 :             szAirRpt.OABalanceMdot = (szHeatBal.MDotOA) * ADSCorrectionFactor;
    2809              :             Real64 const AirDensity =
    2810         1793 :                 Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, szHeatBal.MAT, szHeatBal.airHumRatAvg, std::string());
    2811         1793 :             szAirRpt.OABalanceVolumeCurDensity = (szHeatBal.MDotOA / AirDensity) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2812         1793 :             szAirRpt.OABalanceAirChangeRate = szAirRpt.OABalanceVolumeCurDensity / (state.dataHVACGlobal->TimeStepSys * szVolume);
    2813         1793 :             szAirRpt.OABalanceVdotCurDensity = (szHeatBal.MDotOA / AirDensity) * ADSCorrectionFactor;
    2814         1793 :             szAirRpt.OABalanceVolumeStdDensity =
    2815         1793 :                 (szHeatBal.MDotOA / state.dataEnvrn->StdRhoAir) * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2816         1793 :             szAirRpt.OABalanceVdotStdDensity = (szHeatBal.MDotOA / state.dataEnvrn->StdRhoAir) * ADSCorrectionFactor;
    2817         1793 :             szAirRpt.OABalanceFanElec = szAirRpt.VentilFanElec;
    2818              :         }
    2819              :     }
    2820              :     // Reports exfiltration loss
    2821      3579709 :     H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(state.dataEnvrn->OutHumRat, outDryBulb);
    2822      3579709 :     szAirRpt.SysInletMass = 0;
    2823      3579709 :     szAirRpt.SysOutletMass = 0;
    2824      3579709 :     if (!szEquipConfig.IsControlled) {
    2825       491706 :         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       491706 :         for (int k = 1; k <= szEquipConfig.NumExhaustNodes; ++k) {
    2830            0 :             szAirRpt.SysOutletMass +=
    2831            0 :                 state.dataLoopNodes->Node(szEquipConfig.ExhaustNode(k)).MassFlowRate * state.dataHVACGlobal->TimeStepSysSec * ADSCorrectionFactor;
    2832              :         }
    2833       491706 :         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      3579709 :     szAirRpt.ExfilMass =
    2840      3579709 :         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      3579709 :     szAirRpt.ExfilSensiLoss = szAirRpt.ExfilMass / state.dataHVACGlobal->TimeStepSysSec * (szHeatBal.MAT - outDryBulb) * CpAir; // W
    2843      3579709 :     szAirRpt.ExfilLatentLoss =
    2844      3579709 :         szAirRpt.ExfilMass / state.dataHVACGlobal->TimeStepSysSec * (szHeatBal.airHumRat - state.dataEnvrn->OutHumRat) * H2OHtOfVap;
    2845      3579709 :     szAirRpt.ExfilTotalLoss = szAirRpt.ExfilLatentLoss + szAirRpt.ExfilSensiLoss;
    2846              : 
    2847              :     // Accumulate only for zones
    2848      3579709 :     if (spaceNum == 0) {
    2849      3568713 :         state.dataHeatBal->ZoneTotalExfiltrationHeatLoss += szAirRpt.ExfilTotalLoss * state.dataHVACGlobal->TimeStepSysSec;
    2850      3568713 :         state.dataHeatBal->ZoneTotalExhaustHeatLoss += szAirRpt.ExhTotalLoss * state.dataHVACGlobal->TimeStepSysSec;
    2851              :     }
    2852      3579709 : }
    2853              : 
    2854      2828212 : 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      2828212 :     if (!state.dataHVACGlobal->AirLoopsSimOnce) {
    2873       834992 :         return;
    2874              :     }
    2875              : 
    2876      1993220 :     int NumPrimaryAirSys = state.dataHVACGlobal->NumPrimaryAirSys;
    2877              : 
    2878      1993220 :     if (state.dataHVACMgr->MyOneTimeFlag) {
    2879              :         // set the air loop Any Continuous Fan flag
    2880         2021 :         for (int AirLoopNum = 1; AirLoopNum <= NumPrimaryAirSys; ++AirLoopNum) {
    2881         1221 :             auto &airLoopControlInfo = state.dataAirLoop->AirLoopControlInfo(AirLoopNum);
    2882              : 
    2883         1221 :             if (!airLoopControlInfo.UnitarySys) { // for nonunitary (central) all systems are continuous fan
    2884          743 :                 airLoopControlInfo.AnyContFan = true;
    2885          478 :             } else if (airLoopControlInfo.cycFanSched != nullptr) { // for unitary systems check the cycling fan schedule
    2886          453 :                 airLoopControlInfo.AnyContFan = (airLoopControlInfo.cycFanSched->getMaxVal(state) > 0.0);
    2887              :             } else { // no schedule means always cycling fan
    2888           25 :                 airLoopControlInfo.AnyContFan = false;
    2889              :             }
    2890              :         }
    2891              :         // check to see if a controlled zone is served exclusively by a zonal system
    2892         5995 :         for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
    2893         5195 :             auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum);
    2894         5195 :             bool airLoopFound = false;
    2895         9938 :             for (int zoneInNode = 1; zoneInNode <= zoneEquipConfig.NumInletNodes; ++zoneInNode) {
    2896         4743 :                 if (zoneEquipConfig.InletNodeAirLoopNum(zoneInNode) > 0) {
    2897         3801 :                     airLoopFound = true;
    2898              :                 }
    2899              :             }
    2900         5195 :             if (!airLoopFound && zoneEquipConfig.NumInletNodes == zoneEquipConfig.NumExhaustNodes) {
    2901         1200 :                 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         5995 :         for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
    2907         5195 :             auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum);
    2908         5195 :             if (!zoneEquipConfig.IsControlled) {
    2909          739 :                 continue;
    2910              :             }
    2911         4456 :             bool CyclingFan = false; // TRUE means air loop operates in cycling fan mode at some point
    2912         9199 :             for (int zoneInNode = 1; zoneInNode <= zoneEquipConfig.NumInletNodes; ++zoneInNode) {
    2913         4743 :                 int AirLoopNum = zoneEquipConfig.InletNodeAirLoopNum(zoneInNode);
    2914         4743 :                 if (AirLoopNum > 0) {
    2915         3801 :                     if (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).cycFanSched != nullptr) {
    2916          577 :                         CyclingFan = state.dataAirLoop->AirLoopControlInfo(AirLoopNum).cycFanSched->hasVal(state, 0.0);
    2917              :                     }
    2918              :                 }
    2919              :             }
    2920         4456 :             if (zoneEquipConfig.ZonalSystemOnly || CyclingFan) {
    2921          849 :                 auto const &thisZone = state.dataHeatBal->Zone(ControlledZoneNum);
    2922          849 :                 if (thisZone.RefrigCaseRA) {
    2923            8 :                     ShowWarningError(state,
    2924            8 :                                      format("For zone={} return air cooling by refrigerated cases will be applied to the zone air.", thisZone.Name));
    2925           12 :                     ShowContinueError(state, "  This zone has no return air or is served by an on/off HVAC system.");
    2926              :                 }
    2927        28763 :                 for (int LightNum = 1; LightNum <= state.dataHeatBal->TotLights; ++LightNum) {
    2928        27934 :                     if (state.dataHeatBal->Lights(LightNum).ZonePtr != ControlledZoneNum) {
    2929        27056 :                         continue;
    2930              :                     }
    2931          878 :                     if (state.dataHeatBal->Lights(LightNum).FractionReturnAir > 0.0) {
    2932           40 :                         ShowWarningError(state,
    2933           40 :                                          format("For zone={} return air heat gain from lights will be applied to the zone air.", thisZone.Name));
    2934           40 :                         ShowContinueError(state, "  This zone has no return air or is served by an on/off HVAC system.");
    2935           20 :                         break;
    2936              :                     }
    2937              :                 }
    2938         1698 :                 for (int spaceNum : thisZone.spaceIndexes) {
    2939          849 :                     auto const &thisSpace = state.dataHeatBal->space(spaceNum);
    2940         8163 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    2941         7314 :                         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          849 :                 }
    2949              :             }
    2950              :         }
    2951          800 :         state.dataHVACMgr->MyOneTimeFlag = false;
    2952              :     }
    2953              : 
    2954              :     // set the air loop fan operation mode
    2955      4707666 :     for (int AirLoopNum = 1; AirLoopNum <= NumPrimaryAirSys; ++AirLoopNum) {
    2956      2714446 :         auto &airLoopControlInfo = state.dataAirLoop->AirLoopControlInfo(AirLoopNum);
    2957      2714446 :         if (airLoopControlInfo.cycFanSched != nullptr) {
    2958      1020961 :             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     14171021 :     for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
    2964     12177801 :         auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum);
    2965     12177801 :         auto &thisZone = state.dataHeatBal->Zone(ControlledZoneNum);
    2966     12177801 :         if (!zoneEquipConfig.IsControlled) {
    2967      1716089 :             continue;
    2968              :         }
    2969     10461712 :         thisZone.NoHeatToReturnAir = true;
    2970     10461712 :         if (!zoneEquipConfig.ZonalSystemOnly) {
    2971     11493485 :             for (int zoneInNode = 1; zoneInNode <= zoneEquipConfig.NumInletNodes; ++zoneInNode) {
    2972     10008165 :                 int AirLoopNum = zoneEquipConfig.InletNodeAirLoopNum(zoneInNode);
    2973     10008165 :                 if (AirLoopNum > 0) {
    2974      8762617 :                     if (state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp == HVAC::FanOp::Continuous) {
    2975      8093197 :                         thisZone.NoHeatToReturnAir = false;
    2976      8093197 :                         break;
    2977              :                     }
    2978              :                 }
    2979              :             }
    2980              :         }
    2981              :     }
    2982              : }
    2983              : 
    2984      3144109 : void UpdateZoneInletConvergenceLog(EnergyPlusData &state)
    2985              : {
    2986              : 
    2987      3144109 :     std::array<Real64, DataConvergParams::ConvergLogStackDepth> tmpRealARR = {};
    2988              : 
    2989     28353400 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2990              : 
    2991     48607333 :         for (int NodeIndex = 1; NodeIndex <= state.dataConvergeParams->ZoneInletConvergence(ZoneNum).NumInletNodes; ++NodeIndex) {
    2992     23398042 :             int NodeNum = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).NodeNum;
    2993              : 
    2994     23398042 :             tmpRealARR = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio;
    2995     23398042 :             state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio[0] = state.dataLoopNodes->Node(NodeNum).HumRat;
    2996    233980420 :             for (int logIndex = 1; logIndex < DataConvergParams::ConvergLogStackDepth; logIndex++) {
    2997    210582378 :                 state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).HumidityRatio[logIndex] = tmpRealARR[logIndex - 1];
    2998              :             }
    2999              : 
    3000     23398042 :             tmpRealARR = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate;
    3001     23398042 :             state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate[0] =
    3002     23398042 :                 state.dataLoopNodes->Node(NodeNum).MassFlowRate;
    3003    233980420 :             for (int logIndex = 1; logIndex < DataConvergParams::ConvergLogStackDepth; logIndex++) {
    3004    210582378 :                 state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).MassFlowRate[logIndex] = tmpRealARR[logIndex - 1];
    3005              :             }
    3006              : 
    3007     23398042 :             tmpRealARR = state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature;
    3008     23398042 :             state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature[0] = state.dataLoopNodes->Node(NodeNum).Temp;
    3009    233980420 :             for (int logIndex = 1; logIndex < DataConvergParams::ConvergLogStackDepth; logIndex++) {
    3010    210582378 :                 state.dataConvergeParams->ZoneInletConvergence(ZoneNum).InletNode(NodeIndex).Temperature[logIndex] = tmpRealARR[logIndex - 1];
    3011              :             }
    3012              :         }
    3013              :     }
    3014      3144109 : }
    3015              : 
    3016      2854666 : void CheckAirLoopFlowBalance(EnergyPlusData &state)
    3017              : {
    3018              :     // Check for unbalanced airloop
    3019      2854666 :     if (!state.dataGlobal->WarmupFlag && state.dataHVACGlobal->AirLoopsSimOnce) {
    3020      1671957 :         for (int AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) {
    3021       987245 :             auto &thisAirLoopFlow = state.dataAirLoop->AirLoopFlow(AirLoopNum);
    3022       987245 :             if (!thisAirLoopFlow.FlowError) {
    3023       987155 :                 Real64 unbalancedExhaustDelta = thisAirLoopFlow.SupFlow - thisAirLoopFlow.OAFlow - thisAirLoopFlow.SysRetFlow;
    3024       987155 :                 if (unbalancedExhaustDelta > HVAC::SmallMassFlow) {
    3025            2 :                     ShowSevereError(state,
    3026            2 :                                     format("CheckAirLoopFlowBalance: AirLoopHVAC {} is unbalanced. Supply is > return plus outdoor air.",
    3027            1 :                                            state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name));
    3028            2 :                     ShowContinueErrorTimeStamp(state, "");
    3029            2 :                     ShowContinueError(state,
    3030            2 :                                       format("  Flows [m3/s at standard density]: Supply={:.6R}  Return={:.6R}  Outdoor Air={:.6R}",
    3031            1 :                                              thisAirLoopFlow.SupFlow / state.dataEnvrn->StdRhoAir,
    3032            1 :                                              thisAirLoopFlow.SysRetFlow / state.dataEnvrn->StdRhoAir,
    3033            1 :                                              thisAirLoopFlow.OAFlow / state.dataEnvrn->StdRhoAir));
    3034            1 :                     ShowContinueError(state, format("  Imbalance={:.6R}", unbalancedExhaustDelta / state.dataEnvrn->StdRhoAir));
    3035            2 :                     ShowContinueError(state, "  This error will only be reported once per system.");
    3036            1 :                     thisAirLoopFlow.FlowError = true;
    3037              :                 }
    3038              :             }
    3039              :         }
    3040              :     }
    3041      2854666 : }
    3042              : 
    3043            0 : 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            0 :     std::string_view const CaseName = ConvErrorCallString[(int)callType];
    3053              : 
    3054            0 :     auto &arrayRef = HVACNotConverged;
    3055            0 :     if (std::any_of(std::begin(arrayRef), std::end(arrayRef), [](bool i) { return i; })) {
    3056              : 
    3057            0 :         ShowContinueError(
    3058            0 :             state, format("Air System Named = {} did not converge for {}", state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).AirLoopName, CaseName));
    3059            0 :         ShowContinueError(state, "Check values should be zero. Most Recent values listed first.");
    3060            0 :         std::string HistoryTrace;
    3061            0 :         for (int StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
    3062            0 :             HistoryTrace += format("{:.6R},", DemandToSupply[StackDepth]);
    3063              :         }
    3064            0 :         ShowContinueError(state, format("Demand-to-Supply interface {} check value iteration history trace: {}", CaseName, HistoryTrace));
    3065            0 :         HistoryTrace = "";
    3066            0 :         for (int StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
    3067            0 :             HistoryTrace += format("{:.6R},", SupplyDeck1ToDemand[StackDepth]);
    3068              :         }
    3069            0 :         ShowContinueError(state, format("Supply-to-demand interface deck 1 {} check value iteration history trace: {}", CaseName, HistoryTrace));
    3070              : 
    3071            0 :         if (state.dataAirLoop->AirToZoneNodeInfo(AirSysNum).NumSupplyNodes >= 2) {
    3072            0 :             HistoryTrace = "";
    3073            0 :             for (int StackDepth = 0; StackDepth < DataConvergParams::ConvergLogStackDepth; ++StackDepth) {
    3074            0 :                 HistoryTrace += format("{:.6R},", SupplyDeck2ToDemand[StackDepth]);
    3075              :             }
    3076            0 :             ShowContinueError(state, format("Supply-to-demand interface deck 2 {} check value iteration history trace: {}", CaseName, HistoryTrace));
    3077              :         }
    3078            0 :     } // energy not converged
    3079            0 : }
    3080              : } // namespace EnergyPlus::HVACManager
        

Generated by: LCOV version 2.0-1