LCOV - code coverage report
Current view: top level - EnergyPlus - ZoneContaminantPredictorCorrector.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1008 1516 66.5 %
Date: 2024-08-24 18:31:18 Functions: 9 10 90.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, 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 <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Array.functions.hh>
      53             : #include <ObjexxFCL/Array1D.hh>
      54             : #include <ObjexxFCL/Fmath.hh>
      55             : 
      56             : // EnergyPlus Headers
      57             : #include <AirflowNetwork/Elements.hpp>
      58             : #include <AirflowNetwork/Solver.hpp>
      59             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60             : #include <EnergyPlus/DataDefineEquip.hh>
      61             : #include <EnergyPlus/DataEnvironment.hh>
      62             : #include <EnergyPlus/DataHVACGlobals.hh>
      63             : #include <EnergyPlus/DataHeatBalFanSys.hh>
      64             : #include <EnergyPlus/DataHeatBalance.hh>
      65             : #include <EnergyPlus/DataIPShortCuts.hh>
      66             : #include <EnergyPlus/DataLoopNode.hh>
      67             : #include <EnergyPlus/DataSurfaces.hh>
      68             : #include <EnergyPlus/DataZoneEquipment.hh>
      69             : #include <EnergyPlus/General.hh>
      70             : #include <EnergyPlus/HeatBalanceInternalHeatGains.hh>
      71             : #include <EnergyPlus/HybridModel.hh>
      72             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      73             : #include <EnergyPlus/InternalHeatGains.hh>
      74             : #include <EnergyPlus/OutputProcessor.hh>
      75             : #include <EnergyPlus/Psychrometrics.hh>
      76             : #include <EnergyPlus/ScheduleManager.hh>
      77             : #include <EnergyPlus/UtilityRoutines.hh>
      78             : #include <EnergyPlus/ZoneContaminantPredictorCorrector.hh>
      79             : #include <EnergyPlus/ZonePlenum.hh>
      80             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      81             : 
      82             : namespace EnergyPlus::ZoneContaminantPredictorCorrector {
      83             : 
      84             : // MODULE INFORMATION:
      85             : //       AUTHOR         Lixing Gu
      86             : //       DATE WRITTEN   May, 2010
      87             : 
      88             : // PURPOSE OF THIS MODULE:
      89             : // This module contains routines to predict and correct zone contaminants.
      90             : //  also includes zone contaminant controlling
      91             : 
      92             : // METHODOLOGY EMPLOYED:
      93             : // Similar approach to ZoneTempPredictorCorrector
      94             : 
      95             : // Using/Aliasing
      96             : using namespace DataHeatBalance;
      97             : using namespace Psychrometrics;
      98             : using namespace HybridModel;
      99             : 
     100      234330 : void ManageZoneContaminanUpdates(EnergyPlusData &state,
     101             :                                  DataHeatBalFanSys::PredictorCorrectorCtrl const UpdateType, // Can be iGetZoneSetPoints, iPredictStep, iCorrectStep
     102             :                                  bool const ShortenTimeStepSys,
     103             :                                  bool const UseZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
     104             :                                  Real64 const PriorTimeStep         // the old value for timestep length is passed for possible use in interpolating
     105             : )
     106             : {
     107             : 
     108             :     // SUBROUTINE INFORMATION
     109             :     //       AUTHOR         Lixing Gu
     110             :     //       DATE WRITTEN   July, 2010
     111             : 
     112             :     // PURPOSE OF THIS SUBROUTINE:
     113             :     // This subroutine predicts or corrects the zone air temperature
     114             :     // depending on the simulation status and determines the correct
     115             :     // temperature setpoint for each zone from the schedule manager.
     116             :     // This module is revised from subroutine ManageZoneAirUpdates in
     117             :     // ZoneTempPredictorCorrector module.
     118             : 
     119      234330 :     if (state.dataZoneContaminantPredictorCorrector->GetZoneAirContamInputFlag) {
     120          16 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) GetZoneContaminanInputs(state);
     121          16 :         GetZoneContaminanSetPoints(state);
     122          16 :         state.dataZoneContaminantPredictorCorrector->GetZoneAirContamInputFlag = false;
     123             :     }
     124             : 
     125      234330 :     if (!state.dataContaminantBalance->Contaminant.SimulateContaminants) return;
     126             : 
     127      234330 :     switch (UpdateType) {
     128       41703 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints: {
     129       41703 :         InitZoneContSetPoints(state);
     130       41703 :     } break;
     131       64209 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep: {
     132       64209 :         PredictZoneContaminants(state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
     133       64209 :     } break;
     134       64209 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep: {
     135       64209 :         CorrectZoneContaminants(state, UseZoneTimeStepHistory);
     136       64209 :     } break;
     137           0 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::RevertZoneTimestepHistories: {
     138           0 :         RevertZoneTimestepHistories(state);
     139           0 :     } break;
     140       41703 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories: {
     141       41703 :         PushZoneTimestepHistories(state);
     142       41703 :     } break;
     143       22506 :     case DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories: {
     144       22506 :         PushSystemTimestepHistories(state);
     145       22506 :     } break;
     146           0 :     default:
     147           0 :         break;
     148             :     }
     149             : }
     150             : 
     151           3 : void GetZoneContaminanInputs(EnergyPlusData &state)
     152             : {
     153             : 
     154             :     // SUBROUTINE INFORMATION:
     155             :     //       AUTHOR         Lixing Gu
     156             :     //       DATE WRITTEN   Dec. 2011
     157             : 
     158             :     // PURPOSE OF THIS SUBROUTINE:
     159             :     // This subroutine gets the inputs related to generic contaminant internal gain.
     160             : 
     161             :     // METHODOLOGY EMPLOYED:
     162             :     // Uses the status flags to trigger events.
     163             : 
     164             :     // SUBROUTINE PARAMETER DEFINITIONS:
     165             :     static constexpr std::string_view RoutineName("GetSourcesAndSinks: ");
     166             : 
     167             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     168           3 :     Array1D_string AlphaName;
     169           3 :     Array1D<Real64> IHGNumbers;
     170             :     Real64 SchMin;
     171             :     Real64 SchMax;
     172             :     int IOStat;
     173             :     int Loop;
     174             :     int ZonePtr;
     175           3 :     bool ErrorsFound(false);
     176           3 :     Array1D_bool RepVarSet;
     177           3 :     std::string CurrentModuleObject;
     178             : 
     179           3 :     RepVarSet.dimension(state.dataGlobal->NumOfZones, true);
     180             : 
     181           3 :     int NumAlpha = 0;
     182           3 :     int NumNumber = 0;
     183           3 :     int MaxAlpha = -100;
     184           3 :     int MaxNumber = -100;
     185           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:Constant";
     186           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     187           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     188           3 :     MaxNumber = max(MaxNumber, NumNumber);
     189           3 :     CurrentModuleObject = "SurfaceContaminantSourceAndSink:Generic:PressureDriven";
     190           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     191           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     192           3 :     MaxNumber = max(MaxNumber, NumNumber);
     193           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:CutoffModel";
     194           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     195           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     196           3 :     MaxNumber = max(MaxNumber, NumNumber);
     197           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:DecaySource";
     198           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     199           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     200           3 :     MaxNumber = max(MaxNumber, NumNumber);
     201           3 :     CurrentModuleObject = "SurfaceContaminantSourceAndSink:Generic:BoundaryLayerDiffusion";
     202           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     203           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     204           3 :     MaxNumber = max(MaxNumber, NumNumber);
     205           3 :     CurrentModuleObject = "SurfaceContaminantSourceAndSink:Generic:DepositionVelocitySink";
     206           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     207           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     208           3 :     MaxNumber = max(MaxNumber, NumNumber);
     209           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:DepositionRateSink";
     210           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Loop, NumAlpha, NumNumber);
     211           3 :     MaxAlpha = max(MaxAlpha, NumAlpha);
     212           3 :     MaxNumber = max(MaxNumber, NumNumber);
     213           3 :     IHGNumbers.allocate(MaxNumber);
     214           3 :     AlphaName.allocate(MaxAlpha);
     215           3 :     IHGNumbers = 0.0;
     216           3 :     AlphaName = "";
     217             : 
     218           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:Constant";
     219           3 :     int TotGCGenConstant = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     220           3 :     state.dataContaminantBalance->ZoneContamGenericConstant.allocate(TotGCGenConstant);
     221             : 
     222           9 :     for (Loop = 1; Loop <= TotGCGenConstant; ++Loop) {
     223           6 :         AlphaName = "";
     224           6 :         IHGNumbers = 0.0;
     225          12 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     226             :                                                                  CurrentModuleObject,
     227             :                                                                  Loop,
     228             :                                                                  AlphaName,
     229             :                                                                  NumAlpha,
     230             :                                                                  IHGNumbers,
     231             :                                                                  NumNumber,
     232             :                                                                  IOStat,
     233           6 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     234           6 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     235           6 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     236           6 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     237           6 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
     238           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).Name = AlphaName(1);
     239             : 
     240           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).ZoneName = AlphaName(2);
     241           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).ActualZoneNum = Util::FindItemInList(AlphaName(2), state.dataHeatBal->Zone);
     242           6 :         if (state.dataContaminantBalance->ZoneContamGenericConstant(Loop).ActualZoneNum == 0) {
     243           0 :             ShowSevereError(state,
     244           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
     245             :                                    RoutineName,
     246             :                                    CurrentModuleObject,
     247             :                                    AlphaName(1),
     248           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
     249             :                                    AlphaName(2)));
     250           0 :             ErrorsFound = true;
     251             :         }
     252             : 
     253           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenerateRateSchedPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
     254           6 :         if (state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenerateRateSchedPtr == 0) {
     255           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     256           0 :                 ShowSevereError(
     257             :                     state,
     258           0 :                     format(
     259           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
     260             :             } else {
     261           0 :                 ShowSevereError(state,
     262           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
     263             :                                        RoutineName,
     264             :                                        CurrentModuleObject,
     265             :                                        AlphaName(1),
     266           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     267             :                                        AlphaName(3)));
     268             :             }
     269           0 :             ErrorsFound = true;
     270             :         } else { // check min/max on schedule
     271           6 :             SchMin =
     272           6 :                 ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenerateRateSchedPtr);
     273           6 :             SchMax =
     274           6 :                 ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenerateRateSchedPtr);
     275           6 :             if (SchMin < 0.0 || SchMax < 0.0) {
     276           0 :                 if (SchMin < 0.0) {
     277           0 :                     ShowSevereError(state,
     278           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
     279             :                                            RoutineName,
     280             :                                            CurrentModuleObject,
     281             :                                            AlphaName(1),
     282           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     283           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
     284           0 :                     ErrorsFound = true;
     285             :                 }
     286           0 :                 if (SchMax < 0.0) {
     287           0 :                     ShowSevereError(state,
     288           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
     289             :                                            RoutineName,
     290             :                                            CurrentModuleObject,
     291             :                                            AlphaName(1),
     292           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     293           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
     294           0 :                     ErrorsFound = true;
     295             :                 }
     296             :             }
     297             :         }
     298             : 
     299           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenerateRate = IHGNumbers(1);
     300           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCRemovalCoef = IHGNumbers(2);
     301             : 
     302           6 :         state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCRemovalCoefSchedPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(4));
     303           6 :         if (state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCRemovalCoefSchedPtr == 0) {
     304           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     305           0 :                 ShowSevereError(
     306             :                     state,
     307           0 :                     format(
     308           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(4)));
     309             :             } else {
     310           0 :                 ShowSevereError(state,
     311           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
     312             :                                        RoutineName,
     313             :                                        CurrentModuleObject,
     314             :                                        AlphaName(1),
     315           0 :                                        state.dataIPShortCut->cAlphaFieldNames(4),
     316             :                                        AlphaName(4)));
     317             :             }
     318           0 :             ErrorsFound = true;
     319             :         } else { // check min/max on schedule
     320           6 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCRemovalCoefSchedPtr);
     321           6 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCRemovalCoefSchedPtr);
     322           6 :             if (SchMin < 0.0 || SchMax < 0.0) {
     323           0 :                 if (SchMin < 0.0) {
     324           0 :                     ShowSevereError(state,
     325           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
     326             :                                            RoutineName,
     327             :                                            CurrentModuleObject,
     328             :                                            AlphaName(1),
     329           0 :                                            state.dataIPShortCut->cAlphaFieldNames(4)));
     330           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(4), SchMin));
     331           0 :                     ErrorsFound = true;
     332             :                 }
     333           0 :                 if (SchMax < 0.0) {
     334           0 :                     ShowSevereError(state,
     335           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
     336             :                                            RoutineName,
     337             :                                            CurrentModuleObject,
     338             :                                            AlphaName(1),
     339           0 :                                            state.dataIPShortCut->cAlphaFieldNames(4)));
     340           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(4), SchMax));
     341           0 :                     ErrorsFound = true;
     342             :                 }
     343             :             }
     344             :         }
     345             : 
     346           6 :         if (state.dataContaminantBalance->ZoneContamGenericConstant(Loop).ActualZoneNum <= 0) continue; // Error, will be caught and terminated later
     347             : 
     348             :         // Object report variables
     349          12 :         SetupOutputVariable(state,
     350             :                             "Generic Air Contaminant Constant Source Generation Volume Flow Rate",
     351             :                             Constant::Units::m3_s,
     352           6 :                             state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenRate,
     353             :                             OutputProcessor::TimeStepType::Zone,
     354             :                             OutputProcessor::StoreType::Average,
     355           6 :                             state.dataContaminantBalance->ZoneContamGenericConstant(Loop).Name);
     356             : 
     357             :         // Zone total report variables
     358           6 :         ZonePtr = state.dataContaminantBalance->ZoneContamGenericConstant(Loop).ActualZoneNum;
     359           6 :         if (RepVarSet(ZonePtr)) {
     360           6 :             RepVarSet(ZonePtr) = false;
     361          12 :             SetupOutputVariable(state,
     362             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
     363             :                                 Constant::Units::m3_s,
     364           6 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
     365             :                                 OutputProcessor::TimeStepType::Zone,
     366             :                                 OutputProcessor::StoreType::Average,
     367           6 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
     368             :         }
     369           6 :         SetupZoneInternalGain(state,
     370             :                               ZonePtr,
     371           6 :                               state.dataContaminantBalance->ZoneContamGenericConstant(Loop).Name,
     372             :                               DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
     373             :                               nullptr,
     374             :                               nullptr,
     375             :                               nullptr,
     376             :                               nullptr,
     377             :                               nullptr,
     378             :                               nullptr,
     379           6 :                               &state.dataContaminantBalance->ZoneContamGenericConstant(Loop).GCGenRate);
     380             :     }
     381             : 
     382           3 :     CurrentModuleObject = "SurfaceContaminantSourceAndSink:Generic:PressureDriven";
     383           3 :     int TotGCGenPDriven = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     384           3 :     state.dataContaminantBalance->ZoneContamGenericPDriven.allocate(TotGCGenPDriven);
     385             : 
     386           4 :     for (Loop = 1; Loop <= TotGCGenPDriven; ++Loop) {
     387           1 :         AlphaName = "";
     388           1 :         IHGNumbers = 0.0;
     389           2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     390             :                                                                  CurrentModuleObject,
     391             :                                                                  Loop,
     392             :                                                                  AlphaName,
     393             :                                                                  NumAlpha,
     394             :                                                                  IHGNumbers,
     395             :                                                                  NumNumber,
     396             :                                                                  IOStat,
     397           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     398           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     399           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     400           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     401           1 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
     402           1 :         state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).Name = AlphaName(1);
     403             : 
     404           1 :         state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfName = AlphaName(2);
     405           1 :         state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfNum =
     406           1 :             Util::FindItemInList(AlphaName(2), state.afn->MultizoneSurfaceData, &AirflowNetwork::MultizoneSurfaceProp::SurfName);
     407           1 :         if (state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfNum == 0) {
     408           0 :             ShowSevereError(state,
     409           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
     410             :                                    RoutineName,
     411             :                                    CurrentModuleObject,
     412             :                                    AlphaName(1),
     413           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
     414             :                                    AlphaName(2)));
     415           0 :             ShowContinueError(state, "which is not listed in AirflowNetwork:MultiZone:Surface.");
     416           0 :             ErrorsFound = true;
     417             :         }
     418             :         // Ensure external surface
     419           2 :         if (state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfNum > 0 &&
     420           1 :             state.dataSurface->Surface(state.afn->MultizoneSurfaceData(state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfNum).SurfNum)
     421           1 :                     .ExtBoundCond != DataSurfaces::ExternalEnvironment) {
     422           0 :             ShowSevereError(
     423             :                 state,
     424           0 :                 format(
     425             :                     "{}{}=\"{}. The entered surface ({}) is not an exterior surface", RoutineName, CurrentModuleObject, AlphaName(1), AlphaName(2)));
     426           0 :             ErrorsFound = true;
     427             :         }
     428             : 
     429           1 :         state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRateCoefSchedPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
     430           1 :         if (state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRateCoefSchedPtr == 0) {
     431           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     432           0 :                 ShowSevereError(
     433             :                     state,
     434           0 :                     format(
     435           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
     436             :             } else {
     437           0 :                 ShowSevereError(state,
     438           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
     439             :                                        RoutineName,
     440             :                                        CurrentModuleObject,
     441             :                                        AlphaName(1),
     442           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     443             :                                        AlphaName(3)));
     444             :             }
     445           0 :             ErrorsFound = true;
     446             :         } else { // check min/max on schedule
     447           1 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRateCoefSchedPtr);
     448           1 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRateCoefSchedPtr);
     449           1 :             if (SchMin < 0.0 || SchMax < 0.0) {
     450           0 :                 if (SchMin < 0.0) {
     451           0 :                     ShowSevereError(state,
     452           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
     453             :                                            RoutineName,
     454             :                                            CurrentModuleObject,
     455             :                                            AlphaName(1),
     456           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     457           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
     458           0 :                     ErrorsFound = true;
     459             :                 }
     460           0 :                 if (SchMax < 0.0) {
     461           0 :                     ShowSevereError(state,
     462           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
     463             :                                            RoutineName,
     464             :                                            CurrentModuleObject,
     465             :                                            AlphaName(1),
     466           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     467           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
     468           0 :                     ErrorsFound = true;
     469             :                 }
     470             :             }
     471             :         }
     472             : 
     473           1 :         state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRateCoef = IHGNumbers(1);
     474           1 :         if (IHGNumbers(1) < 0.0) {
     475           0 :             ShowSevereError(state,
     476           0 :                             format("{}Negative values are not allowed for {} in {} = {}",
     477             :                                    RoutineName,
     478           0 :                                    state.dataIPShortCut->cNumericFieldNames(1),
     479             :                                    CurrentModuleObject,
     480             :                                    AlphaName(1)));
     481           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(1)));
     482           0 :             ErrorsFound = true;
     483             :         }
     484             : 
     485           1 :         state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCExpo = IHGNumbers(2);
     486           1 :         if (IHGNumbers(2) <= 0.0) {
     487           0 :             ShowSevereError(state,
     488           0 :                             format("{}Negative or zero value is not allowed for {} in {} = {}",
     489             :                                    RoutineName,
     490           0 :                                    state.dataIPShortCut->cNumericFieldNames(2),
     491             :                                    CurrentModuleObject,
     492             :                                    AlphaName(1)));
     493           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(2)));
     494           0 :             ErrorsFound = true;
     495             :         }
     496           1 :         if (IHGNumbers(2) > 1.0) {
     497           0 :             ShowSevereError(state,
     498           0 :                             format("{}The value greater than 1.0 is not allowed for {} in {} = {}",
     499             :                                    RoutineName,
     500           0 :                                    state.dataIPShortCut->cNumericFieldNames(2),
     501             :                                    CurrentModuleObject,
     502             :                                    AlphaName(1)));
     503           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(2)));
     504           0 :             ErrorsFound = true;
     505             :         }
     506             : 
     507             :         // Object report variables
     508           2 :         SetupOutputVariable(state,
     509             :                             "Generic Air Contaminant Pressure Driven Generation Volume Flow Rate",
     510             :                             Constant::Units::m3_s,
     511           1 :                             state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRate,
     512             :                             OutputProcessor::TimeStepType::Zone,
     513             :                             OutputProcessor::StoreType::Average,
     514           1 :                             state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).Name);
     515             : 
     516           1 :         if (state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfNum > 0) {
     517           1 :             ZonePtr = state.dataSurface
     518           1 :                           ->Surface(state.afn->MultizoneSurfaceData(state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).SurfNum).SurfNum)
     519             :                           .Zone;
     520             :         } else {
     521           0 :             ZonePtr = 0;
     522             :         }
     523             :         // Zone total report variables
     524           1 :         if (ZonePtr > 0 && RepVarSet(ZonePtr)) {
     525           0 :             RepVarSet(ZonePtr) = false;
     526           0 :             SetupOutputVariable(state,
     527             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
     528             :                                 Constant::Units::m3_s,
     529           0 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
     530             :                                 OutputProcessor::TimeStepType::Zone,
     531             :                                 OutputProcessor::StoreType::Average,
     532           0 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
     533             :         }
     534           1 :         if (ZonePtr > 0)
     535           1 :             SetupZoneInternalGain(state,
     536             :                                   ZonePtr,
     537           1 :                                   state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).Name,
     538             :                                   DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
     539             :                                   nullptr,
     540             :                                   nullptr,
     541             :                                   nullptr,
     542             :                                   nullptr,
     543             :                                   nullptr,
     544             :                                   nullptr,
     545           1 :                                   &state.dataContaminantBalance->ZoneContamGenericPDriven(Loop).GCGenRate);
     546             :     }
     547             : 
     548           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:CutoffModel";
     549           3 :     int TotGCGenCutoff = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     550           3 :     state.dataContaminantBalance->ZoneContamGenericCutoff.allocate(TotGCGenCutoff);
     551             : 
     552           5 :     for (Loop = 1; Loop <= TotGCGenCutoff; ++Loop) {
     553           2 :         AlphaName = "";
     554           2 :         IHGNumbers = 0.0;
     555           4 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     556             :                                                                  CurrentModuleObject,
     557             :                                                                  Loop,
     558             :                                                                  AlphaName,
     559             :                                                                  NumAlpha,
     560             :                                                                  IHGNumbers,
     561             :                                                                  NumNumber,
     562             :                                                                  IOStat,
     563           2 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     564           2 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     565           2 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     566           2 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     567           2 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
     568           2 :         state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).Name = AlphaName(1);
     569             : 
     570           2 :         state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).ZoneName = AlphaName(2);
     571           2 :         state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).ActualZoneNum = Util::FindItemInList(AlphaName(2), state.dataHeatBal->Zone);
     572           2 :         if (state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).ActualZoneNum == 0) {
     573           0 :             ShowSevereError(state,
     574           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
     575             :                                    RoutineName,
     576             :                                    CurrentModuleObject,
     577             :                                    AlphaName(1),
     578           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
     579             :                                    AlphaName(2)));
     580           0 :             ErrorsFound = true;
     581             :         }
     582             : 
     583           2 :         state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenerateRateSchedPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
     584           2 :         if (state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenerateRateSchedPtr == 0) {
     585           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     586           0 :                 ShowSevereError(
     587             :                     state,
     588           0 :                     format(
     589           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
     590             :             } else {
     591           0 :                 ShowSevereError(state,
     592           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
     593             :                                        RoutineName,
     594             :                                        CurrentModuleObject,
     595             :                                        AlphaName(1),
     596           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     597             :                                        AlphaName(3)));
     598             :             }
     599           0 :             ErrorsFound = true;
     600             :         } else { // check min/max on schedule
     601           2 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenerateRateSchedPtr);
     602           2 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenerateRateSchedPtr);
     603           2 :             if (SchMin < 0.0 || SchMax < 0.0) {
     604           0 :                 if (SchMin < 0.0) {
     605           0 :                     ShowSevereError(state,
     606           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
     607             :                                            RoutineName,
     608             :                                            CurrentModuleObject,
     609             :                                            AlphaName(1),
     610           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     611           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
     612           0 :                     ErrorsFound = true;
     613             :                 }
     614           0 :                 if (SchMax < 0.0) {
     615           0 :                     ShowSevereError(state,
     616           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
     617             :                                            RoutineName,
     618             :                                            CurrentModuleObject,
     619             :                                            AlphaName(1),
     620           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     621           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
     622           0 :                     ErrorsFound = true;
     623             :                 }
     624             :             }
     625             :         }
     626             : 
     627           2 :         state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenerateRate = IHGNumbers(1);
     628           2 :         state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCCutoffValue = IHGNumbers(2);
     629             : 
     630           2 :         if (IHGNumbers(1) < 0.0) {
     631           0 :             ShowSevereError(state,
     632           0 :                             format("{}Negative values are not allowed for {} in {} = {}",
     633             :                                    RoutineName,
     634           0 :                                    state.dataIPShortCut->cNumericFieldNames(1),
     635             :                                    CurrentModuleObject,
     636             :                                    AlphaName(1)));
     637           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(1)));
     638           0 :             ErrorsFound = true;
     639             :         }
     640           2 :         if (IHGNumbers(2) <= 0.0) {
     641           0 :             ShowSevereError(state,
     642           0 :                             format("{}Negative values or zero are not allowed for {} in {} = {}",
     643             :                                    RoutineName,
     644           0 :                                    state.dataIPShortCut->cNumericFieldNames(2),
     645             :                                    CurrentModuleObject,
     646             :                                    AlphaName(1)));
     647           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(2)));
     648           0 :             ErrorsFound = true;
     649             :         }
     650             : 
     651             :         // Object report variables
     652           4 :         SetupOutputVariable(state,
     653             :                             "Generic Air Contaminant Cutoff Model Generation Volume Flow Rate",
     654             :                             Constant::Units::m3_s,
     655           2 :                             state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenRate,
     656             :                             OutputProcessor::TimeStepType::Zone,
     657             :                             OutputProcessor::StoreType::Average,
     658           2 :                             state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).Name);
     659             : 
     660             :         // Zone total report variables
     661           2 :         ZonePtr = state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).ActualZoneNum;
     662           2 :         if (RepVarSet(ZonePtr)) {
     663           0 :             RepVarSet(ZonePtr) = false;
     664           0 :             SetupOutputVariable(state,
     665             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
     666             :                                 Constant::Units::m3_s,
     667           0 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
     668             :                                 OutputProcessor::TimeStepType::Zone,
     669             :                                 OutputProcessor::StoreType::Average,
     670           0 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
     671             :         }
     672           2 :         SetupZoneInternalGain(state,
     673             :                               ZonePtr,
     674           2 :                               state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).Name,
     675             :                               DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
     676             :                               nullptr,
     677             :                               nullptr,
     678             :                               nullptr,
     679             :                               nullptr,
     680             :                               nullptr,
     681             :                               nullptr,
     682           2 :                               &state.dataContaminantBalance->ZoneContamGenericCutoff(Loop).GCGenRate);
     683             :     }
     684             : 
     685           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:DecaySource";
     686           3 :     int TotGCGenDecay = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     687           3 :     state.dataContaminantBalance->ZoneContamGenericDecay.allocate(TotGCGenDecay);
     688             : 
     689           4 :     for (Loop = 1; Loop <= TotGCGenDecay; ++Loop) {
     690           1 :         AlphaName = "";
     691           1 :         IHGNumbers = 0.0;
     692           2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     693             :                                                                  CurrentModuleObject,
     694             :                                                                  Loop,
     695             :                                                                  AlphaName,
     696             :                                                                  NumAlpha,
     697             :                                                                  IHGNumbers,
     698             :                                                                  NumNumber,
     699             :                                                                  IOStat,
     700           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     701           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     702           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     703           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     704           1 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
     705           1 :         state.dataContaminantBalance->ZoneContamGenericDecay(Loop).Name = AlphaName(1);
     706             : 
     707           1 :         state.dataContaminantBalance->ZoneContamGenericDecay(Loop).ZoneName = AlphaName(2);
     708           1 :         state.dataContaminantBalance->ZoneContamGenericDecay(Loop).ActualZoneNum = Util::FindItemInList(AlphaName(2), state.dataHeatBal->Zone);
     709           1 :         if (state.dataContaminantBalance->ZoneContamGenericDecay(Loop).ActualZoneNum == 0) {
     710           0 :             ShowSevereError(state,
     711           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
     712             :                                    RoutineName,
     713             :                                    CurrentModuleObject,
     714             :                                    AlphaName(1),
     715           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
     716             :                                    AlphaName(2)));
     717           0 :             ErrorsFound = true;
     718             :         }
     719             : 
     720           1 :         state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCEmiRateSchedPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
     721           1 :         if (state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCEmiRateSchedPtr == 0) {
     722           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     723           0 :                 ShowSevereError(
     724             :                     state,
     725           0 :                     format(
     726           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
     727             :             } else {
     728           0 :                 ShowSevereError(state,
     729           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
     730             :                                        RoutineName,
     731             :                                        CurrentModuleObject,
     732             :                                        AlphaName(1),
     733           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     734             :                                        AlphaName(3)));
     735             :             }
     736           0 :             ErrorsFound = true;
     737             :         } else { // check min/max on schedule
     738           1 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCEmiRateSchedPtr);
     739           1 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCEmiRateSchedPtr);
     740           1 :             if (SchMin < 0.0 || SchMax < 0.0) {
     741           0 :                 if (SchMin < 0.0) {
     742           0 :                     ShowSevereError(state,
     743           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
     744             :                                            RoutineName,
     745             :                                            CurrentModuleObject,
     746             :                                            AlphaName(1),
     747           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     748           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
     749           0 :                     ErrorsFound = true;
     750             :                 }
     751           0 :                 if (SchMax < 0.0) {
     752           0 :                     ShowSevereError(state,
     753           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
     754             :                                            RoutineName,
     755             :                                            CurrentModuleObject,
     756             :                                            AlphaName(1),
     757           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     758           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
     759           0 :                     ErrorsFound = true;
     760             :                 }
     761             :             }
     762             :         }
     763             : 
     764           1 :         state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCInitEmiRate = IHGNumbers(1);
     765           1 :         state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCDelayTime = IHGNumbers(2);
     766             : 
     767           1 :         if (IHGNumbers(1) < 0.0) {
     768           0 :             ShowSevereError(state,
     769           0 :                             format("{}Negative values are not allowed for {} in {} = {}",
     770             :                                    RoutineName,
     771           0 :                                    state.dataIPShortCut->cNumericFieldNames(1),
     772             :                                    CurrentModuleObject,
     773             :                                    AlphaName(1)));
     774           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(1)));
     775           0 :             ErrorsFound = true;
     776             :         }
     777           1 :         if (IHGNumbers(2) <= 0.0) {
     778           0 :             ShowSevereError(state,
     779           0 :                             format("{}Negative values or zero are not allowed for {} in {} = {}",
     780             :                                    RoutineName,
     781           0 :                                    state.dataIPShortCut->cNumericFieldNames(2),
     782             :                                    CurrentModuleObject,
     783             :                                    AlphaName(1)));
     784           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(2)));
     785           0 :             ErrorsFound = true;
     786             :         }
     787             : 
     788             :         // Object report variables
     789           2 :         SetupOutputVariable(state,
     790             :                             "Generic Air Contaminant Decay Model Generation Volume Flow Rate",
     791             :                             Constant::Units::m3_s,
     792           1 :                             state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCGenRate,
     793             :                             OutputProcessor::TimeStepType::Zone,
     794             :                             OutputProcessor::StoreType::Average,
     795           1 :                             state.dataContaminantBalance->ZoneContamGenericDecay(Loop).Name);
     796           2 :         SetupOutputVariable(state,
     797             :                             "Generic Air Contaminant Decay Model Generation Emission Start Elapsed Time",
     798             :                             Constant::Units::s,
     799           1 :                             state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCTime,
     800             :                             OutputProcessor::TimeStepType::Zone,
     801             :                             OutputProcessor::StoreType::Average,
     802           1 :                             state.dataContaminantBalance->ZoneContamGenericDecay(Loop).Name);
     803             : 
     804             :         // Zone total report variables
     805           1 :         ZonePtr = state.dataContaminantBalance->ZoneContamGenericDecay(Loop).ActualZoneNum;
     806           1 :         if (RepVarSet(ZonePtr)) {
     807           0 :             RepVarSet(ZonePtr) = false;
     808           0 :             SetupOutputVariable(state,
     809             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
     810             :                                 Constant::Units::m3_s,
     811           0 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
     812             :                                 OutputProcessor::TimeStepType::Zone,
     813             :                                 OutputProcessor::StoreType::Average,
     814           0 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
     815             :         }
     816           1 :         SetupZoneInternalGain(state,
     817             :                               ZonePtr,
     818           1 :                               state.dataContaminantBalance->ZoneContamGenericDecay(Loop).Name,
     819             :                               DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
     820             :                               nullptr,
     821             :                               nullptr,
     822             :                               nullptr,
     823             :                               nullptr,
     824             :                               nullptr,
     825             :                               nullptr,
     826           1 :                               &state.dataContaminantBalance->ZoneContamGenericDecay(Loop).GCGenRate);
     827             :     }
     828             : 
     829           3 :     CurrentModuleObject = "SurfaceContaminantSourceAndSink:Generic:BoundaryLayerDiffusion";
     830           3 :     int TotGCBLDiff = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     831           3 :     state.dataContaminantBalance->ZoneContamGenericBLDiff.allocate(TotGCBLDiff);
     832             : 
     833           4 :     for (Loop = 1; Loop <= TotGCBLDiff; ++Loop) {
     834           1 :         AlphaName = "";
     835           1 :         IHGNumbers = 0.0;
     836           2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     837             :                                                                  CurrentModuleObject,
     838             :                                                                  Loop,
     839             :                                                                  AlphaName,
     840             :                                                                  NumAlpha,
     841             :                                                                  IHGNumbers,
     842             :                                                                  NumNumber,
     843             :                                                                  IOStat,
     844           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     845           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     846           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     847           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     848           1 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
     849           1 :         state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).Name = AlphaName(1);
     850             : 
     851           1 :         state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfName = AlphaName(2);
     852           1 :         state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfNum = Util::FindItemInList(AlphaName(2), state.dataSurface->Surface);
     853           1 :         if (state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfNum == 0) {
     854           0 :             ShowSevereError(state,
     855           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
     856             :                                    RoutineName,
     857             :                                    CurrentModuleObject,
     858             :                                    AlphaName(1),
     859           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
     860             :                                    AlphaName(2)));
     861           0 :             ErrorsFound = true;
     862             :         }
     863             : 
     864           1 :         state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCTranCoefSchedPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
     865           1 :         if (state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCTranCoefSchedPtr == 0) {
     866           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     867           0 :                 ShowSevereError(
     868             :                     state,
     869           0 :                     format(
     870           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
     871             :             } else {
     872           0 :                 ShowSevereError(state,
     873           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
     874             :                                        RoutineName,
     875             :                                        CurrentModuleObject,
     876             :                                        AlphaName(1),
     877           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     878             :                                        AlphaName(3)));
     879             :             }
     880           0 :             ErrorsFound = true;
     881             :         } else { // check min/max on schedule
     882           1 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCTranCoefSchedPtr);
     883           1 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCTranCoefSchedPtr);
     884           1 :             if (SchMin < 0.0 || SchMax < 0.0) {
     885           0 :                 if (SchMin < 0.0) {
     886           0 :                     ShowSevereError(state,
     887           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
     888             :                                            RoutineName,
     889             :                                            CurrentModuleObject,
     890             :                                            AlphaName(1),
     891           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     892           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
     893           0 :                     ErrorsFound = true;
     894             :                 }
     895           0 :                 if (SchMax < 0.0) {
     896           0 :                     ShowSevereError(state,
     897           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
     898             :                                            RoutineName,
     899             :                                            CurrentModuleObject,
     900             :                                            AlphaName(1),
     901           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
     902           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
     903           0 :                     ErrorsFound = true;
     904             :                 }
     905             :             }
     906             :         }
     907             : 
     908           1 :         state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCTranCoef = IHGNumbers(1);
     909           1 :         state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCHenryCoef = IHGNumbers(2);
     910           1 :         if (IHGNumbers(1) < 0.0) {
     911           0 :             ShowSevereError(state,
     912           0 :                             format("{}Negative values are not allowed for {} in {} = {}",
     913             :                                    RoutineName,
     914           0 :                                    state.dataIPShortCut->cNumericFieldNames(1),
     915             :                                    CurrentModuleObject,
     916             :                                    AlphaName(1)));
     917           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(1)));
     918           0 :             ErrorsFound = true;
     919             :         }
     920           1 :         if (IHGNumbers(2) <= 0.0) {
     921           0 :             ShowSevereError(state,
     922           0 :                             format("{}Negative values or zero are not allowed for {} in {} = {}",
     923             :                                    RoutineName,
     924           0 :                                    state.dataIPShortCut->cNumericFieldNames(2),
     925             :                                    CurrentModuleObject,
     926             :                                    AlphaName(1)));
     927           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(2)));
     928           0 :             ErrorsFound = true;
     929             :         }
     930             : 
     931             :         // Object report variables
     932           2 :         SetupOutputVariable(state,
     933             :                             "Generic Air Contaminant Boundary Layer Diffusion Generation Volume Flow Rate",
     934             :                             Constant::Units::m3_s,
     935           1 :                             state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCGenRate,
     936             :                             OutputProcessor::TimeStepType::Zone,
     937             :                             OutputProcessor::StoreType::Average,
     938           1 :                             state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).Name);
     939           1 :         if (state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfNum > 0) {
     940           2 :             SetupOutputVariable(state,
     941             :                                 "Generic Air Contaminant Boundary Layer Diffusion Inside Face Concentration",
     942             :                                 Constant::Units::ppm,
     943           1 :                                 state.dataSurface->SurfGenericContam(state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfNum),
     944             :                                 OutputProcessor::TimeStepType::Zone,
     945             :                                 OutputProcessor::StoreType::Average,
     946           1 :                                 state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfName);
     947             :         }
     948             : 
     949           1 :         ZonePtr = state.dataSurface->Surface(state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).SurfNum).Zone;
     950             :         // Zone total report variables
     951           1 :         if (RepVarSet(ZonePtr)) {
     952           0 :             RepVarSet(ZonePtr) = false;
     953           0 :             SetupOutputVariable(state,
     954             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
     955             :                                 Constant::Units::m3_s,
     956           0 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
     957             :                                 OutputProcessor::TimeStepType::Zone,
     958             :                                 OutputProcessor::StoreType::Average,
     959           0 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
     960             :         }
     961           1 :         SetupZoneInternalGain(state,
     962             :                               ZonePtr,
     963           1 :                               state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).Name,
     964             :                               DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
     965             :                               nullptr,
     966             :                               nullptr,
     967             :                               nullptr,
     968             :                               nullptr,
     969             :                               nullptr,
     970             :                               nullptr,
     971           1 :                               &state.dataContaminantBalance->ZoneContamGenericBLDiff(Loop).GCGenRate);
     972             :     }
     973             : 
     974           3 :     CurrentModuleObject = "SurfaceContaminantSourceAndSink:Generic:DepositionVelocitySink";
     975           3 :     int TotGCDVS = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     976           3 :     state.dataContaminantBalance->ZoneContamGenericDVS.allocate(TotGCDVS);
     977             : 
     978           4 :     for (Loop = 1; Loop <= TotGCDVS; ++Loop) {
     979           1 :         AlphaName = "";
     980           1 :         IHGNumbers = 0.0;
     981           2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     982             :                                                                  CurrentModuleObject,
     983             :                                                                  Loop,
     984             :                                                                  AlphaName,
     985             :                                                                  NumAlpha,
     986             :                                                                  IHGNumbers,
     987             :                                                                  NumNumber,
     988             :                                                                  IOStat,
     989           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     990           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     991           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     992           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     993           1 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
     994           1 :         state.dataContaminantBalance->ZoneContamGenericDVS(Loop).Name = AlphaName(1);
     995             : 
     996           1 :         state.dataContaminantBalance->ZoneContamGenericDVS(Loop).SurfName = AlphaName(2);
     997           1 :         state.dataContaminantBalance->ZoneContamGenericDVS(Loop).SurfNum = Util::FindItemInList(AlphaName(2), state.dataSurface->Surface);
     998           1 :         if (state.dataContaminantBalance->ZoneContamGenericDVS(Loop).SurfNum == 0) {
     999           0 :             ShowSevereError(state,
    1000           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
    1001             :                                    RoutineName,
    1002             :                                    CurrentModuleObject,
    1003             :                                    AlphaName(1),
    1004           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
    1005             :                                    AlphaName(2)));
    1006           0 :             ErrorsFound = true;
    1007             :         }
    1008             : 
    1009           1 :         state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCDepoVeloPtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
    1010           1 :         if (state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCDepoVeloPtr == 0) {
    1011           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    1012           0 :                 ShowSevereError(
    1013             :                     state,
    1014           0 :                     format(
    1015           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
    1016             :             } else {
    1017           0 :                 ShowSevereError(state,
    1018           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
    1019             :                                        RoutineName,
    1020             :                                        CurrentModuleObject,
    1021             :                                        AlphaName(1),
    1022           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    1023             :                                        AlphaName(3)));
    1024             :             }
    1025           0 :             ErrorsFound = true;
    1026             :         } else { // check min/max on schedule
    1027           1 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCDepoVeloPtr);
    1028           1 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCDepoVeloPtr);
    1029           1 :             if (SchMin < 0.0 || SchMax < 0.0) {
    1030           0 :                 if (SchMin < 0.0) {
    1031           0 :                     ShowSevereError(state,
    1032           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
    1033             :                                            RoutineName,
    1034             :                                            CurrentModuleObject,
    1035             :                                            AlphaName(1),
    1036           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
    1037           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
    1038           0 :                     ErrorsFound = true;
    1039             :                 }
    1040           0 :                 if (SchMax < 0.0) {
    1041           0 :                     ShowSevereError(state,
    1042           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
    1043             :                                            RoutineName,
    1044             :                                            CurrentModuleObject,
    1045             :                                            AlphaName(1),
    1046           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
    1047           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
    1048           0 :                     ErrorsFound = true;
    1049             :                 }
    1050             :             }
    1051             :         }
    1052             : 
    1053           1 :         state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCDepoVelo = IHGNumbers(1);
    1054           1 :         if (IHGNumbers(1) < 0.0) {
    1055           0 :             ShowSevereError(state,
    1056           0 :                             format("{}Negative values are not allowed for {} in {} = {}",
    1057             :                                    RoutineName,
    1058           0 :                                    state.dataIPShortCut->cNumericFieldNames(1),
    1059             :                                    CurrentModuleObject,
    1060             :                                    AlphaName(1)));
    1061           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(1)));
    1062           0 :             ErrorsFound = true;
    1063             :         }
    1064             : 
    1065             :         // Object report variables
    1066           2 :         SetupOutputVariable(state,
    1067             :                             "Generic Air Contaminant Deposition Velocity Removal Volume Flow Rate",
    1068             :                             Constant::Units::m3_s,
    1069           1 :                             state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCGenRate,
    1070             :                             OutputProcessor::TimeStepType::Zone,
    1071             :                             OutputProcessor::StoreType::Average,
    1072           1 :                             state.dataContaminantBalance->ZoneContamGenericDVS(Loop).Name);
    1073             : 
    1074           1 :         ZonePtr = state.dataSurface->Surface(state.dataContaminantBalance->ZoneContamGenericDVS(Loop).SurfNum).Zone;
    1075             :         // Zone total report variables
    1076           1 :         if (RepVarSet(ZonePtr)) {
    1077           0 :             RepVarSet(ZonePtr) = false;
    1078           0 :             SetupOutputVariable(state,
    1079             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
    1080             :                                 Constant::Units::m3_s,
    1081           0 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
    1082             :                                 OutputProcessor::TimeStepType::Zone,
    1083             :                                 OutputProcessor::StoreType::Average,
    1084           0 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
    1085             :         }
    1086           1 :         SetupZoneInternalGain(state,
    1087             :                               ZonePtr,
    1088           1 :                               state.dataContaminantBalance->ZoneContamGenericDVS(Loop).Name,
    1089             :                               DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
    1090             :                               nullptr,
    1091             :                               nullptr,
    1092             :                               nullptr,
    1093             :                               nullptr,
    1094             :                               nullptr,
    1095             :                               nullptr,
    1096           1 :                               &state.dataContaminantBalance->ZoneContamGenericDVS(Loop).GCGenRate);
    1097             :     }
    1098             : 
    1099           3 :     CurrentModuleObject = "ZoneContaminantSourceAndSink:Generic:DepositionRateSink";
    1100           3 :     int TotGCDRS = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    1101           3 :     state.dataContaminantBalance->ZoneContamGenericDRS.allocate(TotGCDRS);
    1102             : 
    1103           4 :     for (Loop = 1; Loop <= TotGCDRS; ++Loop) {
    1104           1 :         AlphaName = "";
    1105           1 :         IHGNumbers = 0.0;
    1106           2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1107             :                                                                  CurrentModuleObject,
    1108             :                                                                  Loop,
    1109             :                                                                  AlphaName,
    1110             :                                                                  NumAlpha,
    1111             :                                                                  IHGNumbers,
    1112             :                                                                  NumNumber,
    1113             :                                                                  IOStat,
    1114           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    1115           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    1116           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    1117           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    1118           1 :         Util::IsNameEmpty(state, AlphaName(1), CurrentModuleObject, ErrorsFound);
    1119           1 :         state.dataContaminantBalance->ZoneContamGenericDRS(Loop).Name = AlphaName(1);
    1120             : 
    1121           1 :         state.dataContaminantBalance->ZoneContamGenericDRS(Loop).ZoneName = AlphaName(2);
    1122           1 :         state.dataContaminantBalance->ZoneContamGenericDRS(Loop).ActualZoneNum = Util::FindItemInList(AlphaName(2), state.dataHeatBal->Zone);
    1123           1 :         if (state.dataContaminantBalance->ZoneContamGenericDRS(Loop).ActualZoneNum == 0) {
    1124           0 :             ShowSevereError(state,
    1125           0 :                             format("{}{}=\"{}\", invalid {} entered={}",
    1126             :                                    RoutineName,
    1127             :                                    CurrentModuleObject,
    1128             :                                    AlphaName(1),
    1129           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
    1130             :                                    AlphaName(2)));
    1131           0 :             ErrorsFound = true;
    1132             :         }
    1133             : 
    1134           1 :         state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCDepoRatePtr = ScheduleManager::GetScheduleIndex(state, AlphaName(3));
    1135           1 :         if (state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCDepoRatePtr == 0) {
    1136           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    1137           0 :                 ShowSevereError(
    1138             :                     state,
    1139           0 :                     format(
    1140           0 :                         "{}{}=\"{}\", {} is required.", RoutineName, CurrentModuleObject, AlphaName(1), state.dataIPShortCut->cAlphaFieldNames(3)));
    1141             :             } else {
    1142           0 :                 ShowSevereError(state,
    1143           0 :                                 format("{}{}=\"{}\", invalid {} entered={}",
    1144             :                                        RoutineName,
    1145             :                                        CurrentModuleObject,
    1146             :                                        AlphaName(1),
    1147           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    1148             :                                        AlphaName(3)));
    1149             :             }
    1150           0 :             ErrorsFound = true;
    1151             :         } else { // check min/max on schedule
    1152           1 :             SchMin = ScheduleManager::GetScheduleMinValue(state, state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCDepoRatePtr);
    1153           1 :             SchMax = ScheduleManager::GetScheduleMaxValue(state, state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCDepoRatePtr);
    1154           1 :             if (SchMin < 0.0 || SchMax < 0.0) {
    1155           0 :                 if (SchMin < 0.0) {
    1156           0 :                     ShowSevereError(state,
    1157           0 :                                     format("{}{}=\"{}\", {}, minimum is < 0.0",
    1158             :                                            RoutineName,
    1159             :                                            CurrentModuleObject,
    1160             :                                            AlphaName(1),
    1161           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
    1162           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Minimum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMin));
    1163           0 :                     ErrorsFound = true;
    1164             :                 }
    1165           0 :                 if (SchMax < 0.0) {
    1166           0 :                     ShowSevereError(state,
    1167           0 :                                     format("{}{}=\"{}\", {}, maximum is < 0.0",
    1168             :                                            RoutineName,
    1169             :                                            CurrentModuleObject,
    1170             :                                            AlphaName(1),
    1171           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3)));
    1172           0 :                     ShowContinueError(state, format("Schedule=\"{}\". Maximum is [{:.1R}]. Values must be >= 0.0.", AlphaName(3), SchMax));
    1173           0 :                     ErrorsFound = true;
    1174             :                 }
    1175             :             }
    1176             :         }
    1177             : 
    1178           1 :         state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCDepoRate = IHGNumbers(1);
    1179             : 
    1180           1 :         if (IHGNumbers(1) < 0.0) {
    1181           0 :             ShowSevereError(state,
    1182           0 :                             format("{}Negative values are not allowed for {} in {} = {}",
    1183             :                                    RoutineName,
    1184           0 :                                    state.dataIPShortCut->cNumericFieldNames(1),
    1185             :                                    CurrentModuleObject,
    1186             :                                    AlphaName(1)));
    1187           0 :             ShowContinueError(state, format("The input value is {:.2R}", IHGNumbers(1)));
    1188           0 :             ErrorsFound = true;
    1189             :         }
    1190             : 
    1191             :         // Object report variables
    1192           2 :         SetupOutputVariable(state,
    1193             :                             "Generic Air Contaminant Deposition Rate Removal Volume Flow Rate",
    1194             :                             Constant::Units::m3_s,
    1195           1 :                             state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCGenRate,
    1196             :                             OutputProcessor::TimeStepType::Zone,
    1197             :                             OutputProcessor::StoreType::Average,
    1198           1 :                             state.dataContaminantBalance->ZoneContamGenericDRS(Loop).Name);
    1199             : 
    1200           1 :         ZonePtr = state.dataContaminantBalance->ZoneContamGenericDRS(Loop).ActualZoneNum;
    1201             :         // Zone total report variables
    1202           1 :         if (RepVarSet(ZonePtr)) {
    1203           0 :             RepVarSet(ZonePtr) = false;
    1204           0 :             SetupOutputVariable(state,
    1205             :                                 "Zone Generic Air Contaminant Generation Volume Flow Rate",
    1206             :                                 Constant::Units::m3_s,
    1207           0 :                                 state.dataHeatBal->ZoneRpt(ZonePtr).GCRate,
    1208             :                                 OutputProcessor::TimeStepType::Zone,
    1209             :                                 OutputProcessor::StoreType::Average,
    1210           0 :                                 state.dataHeatBal->Zone(ZonePtr).Name);
    1211             :         }
    1212           1 :         SetupZoneInternalGain(state,
    1213             :                               ZonePtr,
    1214           1 :                               state.dataContaminantBalance->ZoneContamGenericDRS(Loop).Name,
    1215             :                               DataHeatBalance::IntGainType::ZoneContaminantSourceAndSinkGenericContam,
    1216             :                               nullptr,
    1217             :                               nullptr,
    1218             :                               nullptr,
    1219             :                               nullptr,
    1220             :                               nullptr,
    1221             :                               nullptr,
    1222           1 :                               &state.dataContaminantBalance->ZoneContamGenericDRS(Loop).GCGenRate);
    1223             :     }
    1224             : 
    1225           3 :     RepVarSet.deallocate();
    1226           3 :     IHGNumbers.deallocate();
    1227           3 :     AlphaName.deallocate();
    1228             : 
    1229           3 :     if (ErrorsFound) {
    1230           0 :         ShowFatalError(state, "Errors getting Zone Contaminant Sources and Sinks input data.  Preceding condition(s) cause termination.");
    1231             :     }
    1232           3 : }
    1233             : 
    1234          16 : void GetZoneContaminanSetPoints(EnergyPlusData &state)
    1235             : {
    1236             : 
    1237             :     // SUBROUTINE INFORMATION:
    1238             :     //       AUTHOR         Lixing Gu
    1239             :     //       DATE WRITTEN   May 2010
    1240             : 
    1241             :     // PURPOSE OF THIS SUBROUTINE:
    1242             :     // This subroutine gets the inputs related to contaminant control.
    1243             : 
    1244             :     // METHODOLOGY EMPLOYED:
    1245             :     // Uses the status flags to trigger events.
    1246             : 
    1247             :     // Using/Aliasing
    1248             : 
    1249             :     using ScheduleManager::CheckScheduleValue;
    1250             :     using ScheduleManager::CheckScheduleValueMinMax;
    1251             :     using ScheduleManager::GetScheduleIndex;
    1252             :     using ScheduleManager::GetScheduleMaxValue;
    1253             :     using ScheduleManager::GetScheduleMinValue;
    1254             : 
    1255             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1256             :     int ContControlledZoneNum; // The Splitter that you are currently loading input into
    1257             :     int NumAlphas;
    1258             :     int NumNums;
    1259             :     int IOStat;
    1260          16 :     bool ErrorsFound(false);
    1261             :     bool ValidScheduleType;
    1262             : 
    1263             :     struct NeededControlTypes
    1264             :     {
    1265             :         // Members
    1266             :         Array1D_bool MustHave; // 4= the four control types
    1267             :         Array1D_bool DidHave;
    1268             : 
    1269             :         // Default Constructor
    1270             :         NeededControlTypes() : MustHave(4, false), DidHave(4, false)
    1271             :         {
    1272             :         }
    1273             :     };
    1274             : 
    1275             :     struct NeededComfortControlTypes
    1276             :     {
    1277             :         // Members
    1278             :         Array1D_bool MustHave; // 4= the four control types
    1279             :         Array1D_bool DidHave;
    1280             : 
    1281             :         // Default Constructor
    1282             :         NeededComfortControlTypes() : MustHave(12, false), DidHave(12, false)
    1283             :         {
    1284             :         }
    1285             :     };
    1286          16 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
    1287          16 :     cCurrentModuleObject = "ZoneControl:ContaminantController";
    1288          16 :     int NumContControlledZones = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
    1289             : 
    1290          16 :     if (NumContControlledZones > 0) {
    1291           8 :         state.dataContaminantBalance->ContaminantControlledZone.allocate(NumContControlledZones);
    1292             :     }
    1293             : 
    1294          34 :     for (ContControlledZoneNum = 1; ContControlledZoneNum <= NumContControlledZones; ++ContControlledZoneNum) {
    1295          36 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1296             :                                                                  cCurrentModuleObject,
    1297             :                                                                  ContControlledZoneNum,
    1298          18 :                                                                  state.dataIPShortCut->cAlphaArgs,
    1299             :                                                                  NumAlphas,
    1300          18 :                                                                  state.dataIPShortCut->rNumericArgs,
    1301             :                                                                  NumNums,
    1302             :                                                                  IOStat,
    1303          18 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
    1304          18 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
    1305          18 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
    1306          18 :                                                                  state.dataIPShortCut->cNumericFieldNames);
    1307          18 :         Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
    1308             : 
    1309          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).Name = state.dataIPShortCut->cAlphaArgs(1);
    1310          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneName = state.dataIPShortCut->cAlphaArgs(2);
    1311          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ActualZoneNum =
    1312          18 :             Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
    1313          18 :         if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ActualZoneNum == 0) {
    1314           0 :             ShowSevereError(state,
    1315           0 :                             format("{}=\"{}\" invalid {}=\"{}\" not found.",
    1316             :                                    cCurrentModuleObject,
    1317           0 :                                    state.dataIPShortCut->cAlphaArgs(1),
    1318           0 :                                    state.dataIPShortCut->cAlphaFieldNames(2),
    1319           0 :                                    state.dataIPShortCut->cAlphaArgs(2)));
    1320           0 :             ErrorsFound = true;
    1321             :         } else {
    1322             :             //      Zone(ContaminantControlledZone(ContControlledZoneNum)%ActualZoneNum)%TempControlledZoneIndex = ContControlledZoneNum
    1323             :         }
    1324             : 
    1325          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedule = state.dataIPShortCut->cAlphaArgs(3);
    1326          18 :         if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    1327           0 :             state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedPtr =
    1328             :                 ScheduleManager::ScheduleAlwaysOn; // (Returns 1.0)
    1329             :         } else {
    1330          18 :             state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedPtr =
    1331          18 :                 GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
    1332          18 :             if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedPtr == 0) {
    1333           0 :                 ShowSevereError(state,
    1334           0 :                                 format("{}=\"{}\" invalid {}=\"{}\" not found.",
    1335             :                                        cCurrentModuleObject,
    1336           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    1337           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
    1338           0 :                                        state.dataIPShortCut->cAlphaArgs(3)));
    1339           0 :                 ErrorsFound = true;
    1340             :             } else {
    1341             :                 // Check validity of control types.
    1342          18 :                 ValidScheduleType = ScheduleManager::CheckScheduleValueMinMax(
    1343          18 :                     state, state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedPtr, ">=", 0.0, "<=", 1.0);
    1344          18 :                 if (!ValidScheduleType) {
    1345           0 :                     ShowSevereError(state,
    1346           0 :                                     format("{}=\"{}\" invalid range {}=\"{}\"",
    1347             :                                            cCurrentModuleObject,
    1348           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1349           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    1350           0 :                                            state.dataIPShortCut->cAlphaArgs(3)));
    1351           0 :                     ShowContinueError(state, "..contains values outside of range [0,1].");
    1352           0 :                     ErrorsFound = true;
    1353             :                 } else {
    1354          18 :                     state.dataHeatBal->Zone(state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ActualZoneNum)
    1355          36 :                         .ZoneContamControllerSchedIndex = state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedPtr;
    1356             :                 }
    1357             :             }
    1358             :         }
    1359             : 
    1360          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).SetPointSchedName = state.dataIPShortCut->cAlphaArgs(4);
    1361          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).SPSchedIndex =
    1362          18 :             GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
    1363          18 :         if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).SPSchedIndex == 0) {
    1364           0 :             ShowSevereError(state,
    1365           0 :                             format("{}=\"{}\" invalid {}=\"{}\" not found.",
    1366             :                                    cCurrentModuleObject,
    1367           0 :                                    state.dataIPShortCut->cAlphaArgs(1),
    1368           0 :                                    state.dataIPShortCut->cAlphaFieldNames(4),
    1369           0 :                                    state.dataIPShortCut->cAlphaArgs(4)));
    1370           0 :             ErrorsFound = true;
    1371             :         } else {
    1372             :             // Check validity of control types.
    1373          18 :             ValidScheduleType = ScheduleManager::CheckScheduleValueMinMax(
    1374          18 :                 state, state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).SPSchedIndex, ">=", 0.0, "<=", 2000.0);
    1375          18 :             if (!ValidScheduleType) {
    1376           0 :                 ShowSevereError(state,
    1377           0 :                                 format("{}=\"{}\" invalid range {}=\"{}\"",
    1378             :                                        cCurrentModuleObject,
    1379           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    1380           0 :                                        state.dataIPShortCut->cAlphaFieldNames(4),
    1381           0 :                                        state.dataIPShortCut->cAlphaArgs(4)));
    1382           0 :                 ShowContinueError(state, "..contains values outside of range [0,2000 ppm].");
    1383           0 :                 ErrorsFound = true;
    1384             :             }
    1385             :         }
    1386             : 
    1387          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMinCO2SchedName = state.dataIPShortCut->cAlphaArgs(5);
    1388          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMinCO2SchedIndex =
    1389          18 :             GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(5));
    1390          18 :         if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMinCO2SchedIndex > 0) {
    1391             :             // Check validity of control types.
    1392           4 :             ValidScheduleType = ScheduleManager::CheckScheduleValueMinMax(
    1393           4 :                 state, state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMinCO2SchedIndex, ">=", 0.0, "<=", 2000.0);
    1394           4 :             if (!ValidScheduleType) {
    1395           0 :                 ShowSevereError(state,
    1396           0 :                                 format("{}=\"{}\" invalid range {}=\"{}\"",
    1397             :                                        cCurrentModuleObject,
    1398           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    1399           0 :                                        state.dataIPShortCut->cAlphaFieldNames(5),
    1400           0 :                                        state.dataIPShortCut->cAlphaArgs(5)));
    1401           0 :                 ShowContinueError(state, "..contains values outside of range [0,2000 ppm].");
    1402           0 :                 ErrorsFound = true;
    1403             :             } else {
    1404           4 :                 state.dataHeatBal->Zone(state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ActualZoneNum)
    1405           8 :                     .ZoneMinCO2SchedIndex = state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMinCO2SchedIndex;
    1406             :             }
    1407             :         }
    1408             : 
    1409          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMaxCO2SchedName = state.dataIPShortCut->cAlphaArgs(6);
    1410          18 :         state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMaxCO2SchedIndex =
    1411          18 :             GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
    1412          18 :         if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMaxCO2SchedIndex > 0) {
    1413             :             // Check validity of control types.
    1414           4 :             ValidScheduleType = ScheduleManager::CheckScheduleValueMinMax(
    1415           4 :                 state, state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMaxCO2SchedIndex, ">=", 0.0, "<=", 2000.0);
    1416           4 :             if (!ValidScheduleType) {
    1417           0 :                 ShowSevereError(state,
    1418           0 :                                 format("{}=\"{}\" invalid range {}=\"{}\"",
    1419             :                                        cCurrentModuleObject,
    1420           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
    1421           0 :                                        state.dataIPShortCut->cAlphaFieldNames(6),
    1422           0 :                                        state.dataIPShortCut->cAlphaArgs(6)));
    1423           0 :                 ShowContinueError(state, "..contains values outside of range [0,2000 ppm].");
    1424           0 :                 ErrorsFound = true;
    1425             :             } else {
    1426           4 :                 state.dataHeatBal->Zone(state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ActualZoneNum)
    1427           8 :                     .ZoneMaxCO2SchedIndex = state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).ZoneMaxCO2SchedIndex;
    1428             :             }
    1429             :         }
    1430             : 
    1431          18 :         if (NumAlphas > 6) {
    1432           1 :             state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCAvaiSchedule = state.dataIPShortCut->cAlphaArgs(7);
    1433           1 :             if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
    1434           0 :                 state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCAvaiSchedPtr = ScheduleManager::ScheduleAlwaysOn;
    1435             :             } else {
    1436           1 :                 state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCAvaiSchedPtr =
    1437           1 :                     GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(7));
    1438           1 :                 if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).AvaiSchedPtr == 0) {
    1439           0 :                     ShowSevereError(state,
    1440           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
    1441             :                                            cCurrentModuleObject,
    1442           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1443           0 :                                            state.dataIPShortCut->cAlphaFieldNames(3),
    1444           0 :                                            state.dataIPShortCut->cAlphaArgs(7)));
    1445           0 :                     ErrorsFound = true;
    1446             :                 } else {
    1447             :                     // Check validity of control types.
    1448           1 :                     ValidScheduleType = ScheduleManager::CheckScheduleValueMinMax(
    1449           1 :                         state, state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCAvaiSchedPtr, ">=", 0.0, "<=", 1.0);
    1450           1 :                     if (!ValidScheduleType) {
    1451           0 :                         ShowSevereError(state,
    1452           0 :                                         format("{}=\"{}\" invalid range {}=\"{}\"",
    1453             :                                                cCurrentModuleObject,
    1454           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
    1455           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3),
    1456           0 :                                                state.dataIPShortCut->cAlphaArgs(7)));
    1457           0 :                         ShowContinueError(state, "..contains values outside of range [0,1].");
    1458           0 :                         ErrorsFound = true;
    1459             :                     }
    1460             :                 }
    1461             :             }
    1462           1 :             if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
    1463           0 :                 ShowSevereError(state, format("{} \"{}\" is required, but blank.", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(8)));
    1464           0 :                 ErrorsFound = true;
    1465             :             } else {
    1466           1 :                 state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCSetPointSchedName =
    1467           2 :                     state.dataIPShortCut->cAlphaArgs(8);
    1468           1 :                 state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCSPSchedIndex =
    1469           1 :                     GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(8));
    1470           1 :                 if (state.dataContaminantBalance->ContaminantControlledZone(ContControlledZoneNum).GCSPSchedIndex == 0) {
    1471           0 :                     ShowSevereError(state,
    1472           0 :                                     format("{}=\"{}\" invalid {}=\"{}\" not found.",
    1473             :                                            cCurrentModuleObject,
    1474           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1475           0 :                                            state.dataIPShortCut->cAlphaFieldNames(8),
    1476           0 :                                            state.dataIPShortCut->cAlphaArgs(8)));
    1477           0 :                     ErrorsFound = true;
    1478             :                 }
    1479             :             }
    1480             :         }
    1481             : 
    1482             :     } // ContControlledZoneNum
    1483             : 
    1484          16 :     if (ErrorsFound) {
    1485           0 :         ShowFatalError(state, "Errors getting Zone Contaminant Control input data.  Preceding condition(s) cause termination.");
    1486             :     }
    1487          16 : }
    1488             : 
    1489       41703 : void InitZoneContSetPoints(EnergyPlusData &state)
    1490             : {
    1491             : 
    1492             :     // SUBROUTINE INFORMATION:
    1493             :     //       AUTHOR         Lixing Gu
    1494             :     //       DATE WRITTEN   May 2010
    1495             : 
    1496             :     // PURPOSE OF THIS SUBROUTINE:
    1497             :     // This subroutine initializes the data for the zone air contaminant setpoints.
    1498             : 
    1499             :     // METHODOLOGY EMPLOYED:
    1500             :     // Uses the status flags to trigger events.
    1501             : 
    1502             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1503             :     Real64 GCGain; // Zone generic contaminant gain
    1504             :     Real64 Pi;     // Pressue at zone i
    1505             :     Real64 Pj;     // Pressue at zone j
    1506             :     Real64 Sch;    // Schedule value
    1507       41703 :     bool ErrorsFound(false);
    1508             : 
    1509       41703 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1510       39675 :         state.dataContaminantBalance->OutdoorCO2 =
    1511       39675 :             ScheduleManager::GetCurrentScheduleValue(state, state.dataContaminantBalance->Contaminant.CO2OutdoorSchedPtr);
    1512             :     }
    1513             : 
    1514       41703 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1515        7089 :         state.dataContaminantBalance->OutdoorGC =
    1516        7089 :             ScheduleManager::GetCurrentScheduleValue(state, state.dataContaminantBalance->Contaminant.GenericContamOutdoorSchedPtr);
    1517             :     }
    1518             : 
    1519       41703 :     if (state.dataZoneContaminantPredictorCorrector->MyOneTimeFlag) {
    1520             :         // CO2
    1521          16 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1522          15 :             state.dataContaminantBalance->ZoneCO2SetPoint.dimension(state.dataGlobal->NumOfZones, 0.0);
    1523          15 :             state.dataContaminantBalance->CO2PredictedRate.dimension(state.dataGlobal->NumOfZones, 0.0);
    1524          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus1.dimension(state.dataGlobal->NumOfZones, 0.0);
    1525          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1526          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus3.dimension(state.dataGlobal->NumOfZones, 0.0);
    1527          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus4.dimension(state.dataGlobal->NumOfZones, 0.0);
    1528          15 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus1.dimension(state.dataGlobal->NumOfZones, 0.0);
    1529          15 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1530          15 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus3.dimension(state.dataGlobal->NumOfZones, 0.0);
    1531          15 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus4.dimension(state.dataGlobal->NumOfZones, 0.0);
    1532          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus1Temp.dimension(state.dataGlobal->NumOfZones, 0.0);
    1533          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus2Temp.dimension(state.dataGlobal->NumOfZones, 0.0);
    1534          15 :             state.dataContaminantBalance->CO2ZoneTimeMinus3Temp.dimension(state.dataGlobal->NumOfZones, 0.0);
    1535          15 :             state.dataContaminantBalance->ZoneCO2MX.dimension(state.dataGlobal->NumOfZones, 0.0);
    1536          15 :             state.dataContaminantBalance->ZoneCO2M2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1537          15 :             state.dataContaminantBalance->ZoneCO21.dimension(state.dataGlobal->NumOfZones, 0.0);
    1538             : 
    1539          15 :             state.dataContaminantBalance->ZoneSysContDemand.allocate(state.dataGlobal->NumOfZones);
    1540          15 :             state.dataContaminantBalance->ZoneCO2Gain.dimension(state.dataGlobal->NumOfZones, 0.0);
    1541          15 :             state.dataContaminantBalance->ZoneCO2GainFromPeople.dimension(state.dataGlobal->NumOfZones, 0.0);
    1542          15 :             state.dataContaminantBalance->ZoneCO2GainExceptPeople.dimension(state.dataGlobal->NumOfZones, 0.0); // Added for hybrid model
    1543          15 :             state.dataContaminantBalance->MixingMassFlowCO2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1544          15 :             state.dataContaminantBalance->ZoneAirDensityCO.dimension(state.dataGlobal->NumOfZones, 0.0);
    1545          15 :             state.dataContaminantBalance->AZ.dimension(state.dataGlobal->NumOfZones, 0.0);
    1546          15 :             state.dataContaminantBalance->BZ.dimension(state.dataGlobal->NumOfZones, 0.0);
    1547          15 :             state.dataContaminantBalance->CZ.dimension(state.dataGlobal->NumOfZones, 0.0);
    1548             :         }
    1549             : 
    1550          16 :         state.dataContaminantBalance->CONTRAT.dimension(state.dataGlobal->NumOfZones, 0.0);
    1551             : 
    1552             :         // Allocate Derived Types
    1553             : 
    1554          77 :         for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1555             :             // Zone CO2
    1556          61 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1557         114 :                 SetupOutputVariable(state,
    1558             :                                     "Zone Air CO2 Concentration",
    1559             :                                     Constant::Units::ppm,
    1560          57 :                                     state.dataContaminantBalance->ZoneAirCO2(Loop),
    1561             :                                     OutputProcessor::TimeStepType::System,
    1562             :                                     OutputProcessor::StoreType::Average,
    1563          57 :                                     state.dataHeatBal->Zone(Loop).Name);
    1564         114 :                 SetupOutputVariable(state,
    1565             :                                     "Zone Air CO2 Predicted Load to Setpoint Mass Flow Rate",
    1566             :                                     Constant::Units::kg_s,
    1567          57 :                                     state.dataContaminantBalance->CO2PredictedRate(Loop),
    1568             :                                     OutputProcessor::TimeStepType::System,
    1569             :                                     OutputProcessor::StoreType::Average,
    1570          57 :                                     state.dataHeatBal->Zone(Loop).Name);
    1571         114 :                 SetupOutputVariable(state,
    1572             :                                     "Zone Air CO2 Setpoint Concentration",
    1573             :                                     Constant::Units::ppm,
    1574          57 :                                     state.dataContaminantBalance->ZoneCO2SetPoint(Loop),
    1575             :                                     OutputProcessor::TimeStepType::System,
    1576             :                                     OutputProcessor::StoreType::Average,
    1577          57 :                                     state.dataHeatBal->Zone(Loop).Name);
    1578         114 :                 SetupOutputVariable(state,
    1579             :                                     "Zone Air CO2 Internal Gain Volume Flow Rate",
    1580             :                                     Constant::Units::m3_s,
    1581          57 :                                     state.dataContaminantBalance->ZoneCO2Gain(Loop),
    1582             :                                     OutputProcessor::TimeStepType::System,
    1583             :                                     OutputProcessor::StoreType::Average,
    1584          57 :                                     state.dataHeatBal->Zone(Loop).Name);
    1585             :             }
    1586             : 
    1587             :         } // Loop
    1588             : 
    1589             :         // Generic contaminant
    1590          16 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1591           3 :             state.dataContaminantBalance->ZoneGCSetPoint.dimension(state.dataGlobal->NumOfZones, 0.0);
    1592           3 :             state.dataContaminantBalance->GCPredictedRate.dimension(state.dataGlobal->NumOfZones, 0.0);
    1593           3 :             state.dataContaminantBalance->GCZoneTimeMinus1.dimension(state.dataGlobal->NumOfZones, 0.0);
    1594           3 :             state.dataContaminantBalance->GCZoneTimeMinus2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1595           3 :             state.dataContaminantBalance->GCZoneTimeMinus3.dimension(state.dataGlobal->NumOfZones, 0.0);
    1596           3 :             state.dataContaminantBalance->GCZoneTimeMinus4.dimension(state.dataGlobal->NumOfZones, 0.0);
    1597           3 :             state.dataContaminantBalance->DSGCZoneTimeMinus1.dimension(state.dataGlobal->NumOfZones, 0.0);
    1598           3 :             state.dataContaminantBalance->DSGCZoneTimeMinus2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1599           3 :             state.dataContaminantBalance->DSGCZoneTimeMinus3.dimension(state.dataGlobal->NumOfZones, 0.0);
    1600           3 :             state.dataContaminantBalance->DSGCZoneTimeMinus4.dimension(state.dataGlobal->NumOfZones, 0.0);
    1601           3 :             state.dataContaminantBalance->GCZoneTimeMinus1Temp.dimension(state.dataGlobal->NumOfZones, 0.0);
    1602           3 :             state.dataContaminantBalance->GCZoneTimeMinus2Temp.dimension(state.dataGlobal->NumOfZones, 0.0);
    1603           3 :             state.dataContaminantBalance->GCZoneTimeMinus3Temp.dimension(state.dataGlobal->NumOfZones, 0.0);
    1604           3 :             state.dataContaminantBalance->ZoneGCMX.dimension(state.dataGlobal->NumOfZones, 0.0);
    1605           3 :             state.dataContaminantBalance->ZoneGCM2.dimension(state.dataGlobal->NumOfZones, 0.0);
    1606           3 :             state.dataContaminantBalance->ZoneGC1.dimension(state.dataGlobal->NumOfZones, 0.0);
    1607             : 
    1608           3 :             if (!allocated(state.dataContaminantBalance->ZoneSysContDemand))
    1609           1 :                 state.dataContaminantBalance->ZoneSysContDemand.allocate(state.dataGlobal->NumOfZones);
    1610           3 :             state.dataContaminantBalance->ZoneGCGain.dimension(state.dataGlobal->NumOfZones, 0.0);
    1611           3 :             state.dataContaminantBalance->MixingMassFlowGC.dimension(state.dataGlobal->NumOfZones, 0.0);
    1612           3 :             state.dataContaminantBalance->ZoneAirDensityGC.dimension(state.dataGlobal->NumOfZones, 0.0);
    1613           3 :             state.dataContaminantBalance->AZGC.dimension(state.dataGlobal->NumOfZones, 0.0);
    1614           3 :             state.dataContaminantBalance->BZGC.dimension(state.dataGlobal->NumOfZones, 0.0);
    1615           3 :             state.dataContaminantBalance->CZGC.dimension(state.dataGlobal->NumOfZones, 0.0);
    1616             :         }
    1617             : 
    1618          16 :         state.dataContaminantBalance->CONTRATGC.dimension(state.dataGlobal->NumOfZones, 0.0);
    1619             : 
    1620             :         // Allocate Derived Types
    1621             : 
    1622          77 :         for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1623             :             // Zone CO2
    1624          61 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1625          42 :                 SetupOutputVariable(state,
    1626             :                                     "Zone Air Generic Air Contaminant Concentration",
    1627             :                                     Constant::Units::ppm,
    1628          21 :                                     state.dataContaminantBalance->ZoneAirGC(Loop),
    1629             :                                     OutputProcessor::TimeStepType::System,
    1630             :                                     OutputProcessor::StoreType::Average,
    1631          21 :                                     state.dataHeatBal->Zone(Loop).Name);
    1632          42 :                 SetupOutputVariable(state,
    1633             :                                     "Zone Generic Air Contaminant Predicted Load to Setpoint Mass Flow Rate",
    1634             :                                     Constant::Units::kg_s,
    1635          21 :                                     state.dataContaminantBalance->GCPredictedRate(Loop),
    1636             :                                     OutputProcessor::TimeStepType::System,
    1637             :                                     OutputProcessor::StoreType::Average,
    1638          21 :                                     state.dataHeatBal->Zone(Loop).Name);
    1639          42 :                 SetupOutputVariable(state,
    1640             :                                     "Zone Generic Air Contaminant Setpoint Concentration",
    1641             :                                     Constant::Units::ppm,
    1642          21 :                                     state.dataContaminantBalance->ZoneGCSetPoint(Loop),
    1643             :                                     OutputProcessor::TimeStepType::System,
    1644             :                                     OutputProcessor::StoreType::Average,
    1645          21 :                                     state.dataHeatBal->Zone(Loop).Name);
    1646             :             }
    1647             :         } // Loop
    1648             : 
    1649          16 :         state.dataZoneContaminantPredictorCorrector->MyOneTimeFlag = false;
    1650             :     }
    1651             : 
    1652             :     // Do the Begin Environment initializations
    1653       41703 :     if (state.dataZoneContaminantPredictorCorrector->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag) {
    1654          97 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1655          91 :             state.dataContaminantBalance->CONTRAT = 0.0;
    1656          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus1 = state.dataContaminantBalance->OutdoorCO2;
    1657          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus2 = state.dataContaminantBalance->OutdoorCO2;
    1658          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus3 = state.dataContaminantBalance->OutdoorCO2;
    1659          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus4 = state.dataContaminantBalance->OutdoorCO2;
    1660          91 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus1 = state.dataContaminantBalance->OutdoorCO2;
    1661          91 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus2 = state.dataContaminantBalance->OutdoorCO2;
    1662          91 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus3 = state.dataContaminantBalance->OutdoorCO2;
    1663          91 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus4 = state.dataContaminantBalance->OutdoorCO2;
    1664          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus1Temp = 0.0;
    1665          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus2Temp = 0.0;
    1666          91 :             state.dataContaminantBalance->CO2ZoneTimeMinus3Temp = 0.0;
    1667          91 :             state.dataContaminantBalance->ZoneAirCO2Temp = state.dataContaminantBalance->OutdoorCO2;
    1668          91 :             state.dataContaminantBalance->ZoneCO2SetPoint = 0.0;
    1669          91 :             state.dataContaminantBalance->CO2PredictedRate = 0.0;
    1670          91 :             state.dataContaminantBalance->ZoneAirCO2 = state.dataContaminantBalance->OutdoorCO2;
    1671          91 :             state.dataContaminantBalance->ZoneCO21 = state.dataContaminantBalance->OutdoorCO2;
    1672          91 :             state.dataContaminantBalance->ZoneCO2MX = state.dataContaminantBalance->OutdoorCO2;
    1673          91 :             state.dataContaminantBalance->ZoneCO2M2 = state.dataContaminantBalance->OutdoorCO2;
    1674             :         }
    1675          97 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1676          17 :             state.dataContaminantBalance->CONTRAT = 0.0;
    1677          17 :             state.dataContaminantBalance->GCZoneTimeMinus1 = state.dataContaminantBalance->OutdoorGC;
    1678          17 :             state.dataContaminantBalance->GCZoneTimeMinus2 = state.dataContaminantBalance->OutdoorGC;
    1679          17 :             state.dataContaminantBalance->GCZoneTimeMinus3 = state.dataContaminantBalance->OutdoorGC;
    1680          17 :             state.dataContaminantBalance->GCZoneTimeMinus4 = state.dataContaminantBalance->OutdoorGC;
    1681          17 :             state.dataContaminantBalance->DSGCZoneTimeMinus1 = state.dataContaminantBalance->OutdoorGC;
    1682          17 :             state.dataContaminantBalance->DSGCZoneTimeMinus2 = state.dataContaminantBalance->OutdoorGC;
    1683          17 :             state.dataContaminantBalance->DSGCZoneTimeMinus3 = state.dataContaminantBalance->OutdoorGC;
    1684          17 :             state.dataContaminantBalance->DSGCZoneTimeMinus4 = state.dataContaminantBalance->OutdoorGC;
    1685          17 :             state.dataContaminantBalance->GCZoneTimeMinus1Temp = 0.0;
    1686          17 :             state.dataContaminantBalance->GCZoneTimeMinus2Temp = 0.0;
    1687          17 :             state.dataContaminantBalance->GCZoneTimeMinus3Temp = 0.0;
    1688          17 :             state.dataContaminantBalance->ZoneAirGCTemp = state.dataContaminantBalance->OutdoorGC;
    1689          17 :             state.dataContaminantBalance->ZoneGCSetPoint = 0.0;
    1690          17 :             state.dataContaminantBalance->GCPredictedRate = 0.0;
    1691          17 :             state.dataContaminantBalance->ZoneAirGC = state.dataContaminantBalance->OutdoorGC;
    1692          17 :             state.dataContaminantBalance->ZoneGC1 = state.dataContaminantBalance->OutdoorGC;
    1693          17 :             state.dataContaminantBalance->ZoneGCMX = state.dataContaminantBalance->OutdoorGC;
    1694          17 :             state.dataContaminantBalance->ZoneGCM2 = state.dataContaminantBalance->OutdoorGC;
    1695          22 :             for (auto &con : state.dataContaminantBalance->ZoneContamGenericBLDiff) {
    1696           5 :                 state.dataSurface->SurfGenericContam(con.SurfNum) = state.dataContaminantBalance->OutdoorGC;
    1697             :             }
    1698          17 :             if (!state.dataContaminantBalance->ZoneContamGenericDecay.empty())
    1699          10 :                 for (auto &e : state.dataContaminantBalance->ZoneContamGenericDecay)
    1700           5 :                     e.GCTime = 0.0;
    1701             :         }
    1702          97 :         state.dataZoneContaminantPredictorCorrector->MyEnvrnFlag = false;
    1703             :     }
    1704             : 
    1705       41703 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1706       41606 :         state.dataZoneContaminantPredictorCorrector->MyEnvrnFlag = true;
    1707             :     }
    1708             : 
    1709       41703 :     if (allocated(state.dataZoneEquip->ZoneEquipConfig) && state.dataZoneContaminantPredictorCorrector->MyConfigOneTimeFlag) {
    1710          34 :         for (int ContZoneNum = 1; ContZoneNum <= (int)state.dataContaminantBalance->ContaminantControlledZone.size(); ++ContZoneNum) {
    1711          18 :             int ZoneNum = state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum).ActualZoneNum;
    1712          36 :             for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumInletNodes; ++zoneInNode) {
    1713          18 :                 int AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(ZoneNum).InletNodeAirLoopNum(zoneInNode);
    1714          18 :                 state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum).NumOfZones = 0;
    1715         103 :                 for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1716          85 :                     if (!state.dataZoneEquip->ZoneEquipConfig(Loop).IsControlled) continue;
    1717          74 :                     for (int zoneInNode2 = 1; zoneInNode2 <= state.dataZoneEquip->ZoneEquipConfig(Loop).NumInletNodes; ++zoneInNode2) {
    1718          74 :                         if (AirLoopNum == state.dataZoneEquip->ZoneEquipConfig(Loop).InletNodeAirLoopNum(zoneInNode2)) {
    1719          74 :                             ++state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum).NumOfZones;
    1720          74 :                             break; // only count a zone once
    1721             :                         }
    1722             :                     }
    1723             :                 }
    1724          18 :                 if (state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum).NumOfZones > 0) {
    1725          18 :                     state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum)
    1726          18 :                         .ControlZoneNum.allocate(state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum).NumOfZones);
    1727          18 :                     int I = 1;
    1728         103 :                     for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1729          85 :                         if (!state.dataZoneEquip->ZoneEquipConfig(Loop).IsControlled) continue;
    1730          74 :                         for (int zoneInNode2 = 1; zoneInNode2 <= state.dataZoneEquip->ZoneEquipConfig(Loop).NumInletNodes; ++zoneInNode2) {
    1731          74 :                             if (AirLoopNum == state.dataZoneEquip->ZoneEquipConfig(Loop).InletNodeAirLoopNum(zoneInNode2)) {
    1732          74 :                                 state.dataContaminantBalance->ContaminantControlledZone(ContZoneNum).ControlZoneNum(I) = Loop;
    1733          74 :                                 ++I;
    1734          74 :                                 break; // only count a zone once
    1735             :                             }
    1736             :                         }
    1737             :                     }
    1738             :                 } else {
    1739           0 :                     ShowSevereError(state,
    1740           0 :                                     format("ZoneControl:ContaminantController: a corresponding AirLoopHVAC is not found for the controlled zone ={}",
    1741           0 :                                            state.dataHeatBal->Zone(ZoneNum).Name));
    1742           0 :                     ErrorsFound = true;
    1743             :                 }
    1744             :             }
    1745             :         }
    1746          16 :         state.dataZoneContaminantPredictorCorrector->MyConfigOneTimeFlag = false;
    1747          16 :         if (ErrorsFound) {
    1748           0 :             ShowFatalError(state, "ZoneControl:ContaminantController: Program terminates for preceding reason(s).");
    1749             :         }
    1750             :     }
    1751             : 
    1752       85110 :     for (int Loop = 1; Loop <= (int)state.dataContaminantBalance->ContaminantControlledZone.size(); ++Loop) {
    1753       43407 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1754       43407 :             int ZoneNum = state.dataContaminantBalance->ContaminantControlledZone(Loop).ActualZoneNum;
    1755       43407 :             state.dataContaminantBalance->ZoneCO2SetPoint(ZoneNum) =
    1756       43407 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataContaminantBalance->ContaminantControlledZone(Loop).SPSchedIndex);
    1757             :         }
    1758       43407 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1759        2169 :             int ZoneNum = state.dataContaminantBalance->ContaminantControlledZone(Loop).ActualZoneNum;
    1760        2169 :             state.dataContaminantBalance->ZoneGCSetPoint(ZoneNum) =
    1761        2169 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataContaminantBalance->ContaminantControlledZone(Loop).GCSPSchedIndex);
    1762             :         }
    1763             :     }
    1764             : 
    1765             :     // CO2 gain
    1766       41703 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1767      184506 :         for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
    1768      144831 :             state.dataContaminantBalance->ZoneCO2Gain(Loop) = InternalHeatGains::SumAllInternalCO2Gains(state, Loop);
    1769      144831 :             if (state.dataHybridModel->FlagHybridModel_PC) {
    1770        8100 :                 state.dataContaminantBalance->ZoneCO2GainExceptPeople(Loop) = InternalHeatGains::SumAllInternalCO2GainsExceptPeople(state, Loop);
    1771             :             }
    1772      144831 :             std::array<DataHeatBalance::IntGainType, 1> IntGainPeopleArray = {DataHeatBalance::IntGainType::People};
    1773      144831 :             state.dataContaminantBalance->ZoneCO2GainFromPeople(Loop) =
    1774      289662 :                 InternalHeatGains::SumInternalCO2GainsByTypes(state, Loop, IntGainPeopleArray);
    1775             :         }
    1776             :     }
    1777             : 
    1778             :     // Generic contaminant gain
    1779       41703 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1780        7089 :         state.dataContaminantBalance->ZoneGCGain = 0.0;
    1781             :         // from constant model
    1782       19680 :         for (auto &con : state.dataContaminantBalance->ZoneContamGenericConstant) {
    1783       12591 :             int ZoneNum = con.ActualZoneNum;
    1784       12591 :             GCGain = con.GCGenerateRate * ScheduleManager::GetCurrentScheduleValue(state, con.GCGenerateRateSchedPtr) -
    1785       12591 :                      con.GCRemovalCoef * ScheduleManager::GetCurrentScheduleValue(state, con.GCRemovalCoefSchedPtr) *
    1786       12591 :                          state.dataContaminantBalance->ZoneAirGC(ZoneNum) * 1.0e-6;
    1787       12591 :             con.GCGenRate = GCGain;
    1788             :         }
    1789             : 
    1790             :         // from pressure driven model
    1791        7089 :         if (state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
    1792        4056 :             for (auto &con : state.dataContaminantBalance->ZoneContamGenericPDriven) {
    1793        2028 :                 int SurfNum = con.SurfNum;
    1794        2028 :                 Pi = state.afn->AirflowNetworkNodeSimu(state.afn->MultizoneSurfaceData(SurfNum).NodeNums[0]).PZ;
    1795        2028 :                 Pj = state.afn->AirflowNetworkNodeSimu(state.afn->MultizoneSurfaceData(SurfNum).NodeNums[1]).PZ;
    1796        2028 :                 if (Pj >= Pi) {
    1797        1605 :                     GCGain = con.GCGenRateCoef * ScheduleManager::GetCurrentScheduleValue(state, con.GCGenRateCoefSchedPtr) *
    1798        1605 :                              std::pow(Pj - Pi, con.GCExpo);
    1799             :                 } else {
    1800         423 :                     GCGain = 0.0;
    1801             :                 }
    1802        2028 :                 con.GCGenRate = GCGain;
    1803             :             }
    1804             :         }
    1805             : 
    1806             :         // from cutoff model
    1807       11427 :         for (auto &con : state.dataContaminantBalance->ZoneContamGenericCutoff) {
    1808        4338 :             int ZoneNum = con.ActualZoneNum;
    1809        4338 :             if (state.dataContaminantBalance->ZoneAirGC(ZoneNum) < con.GCCutoffValue) {
    1810        4338 :                 GCGain = con.GCGenerateRate * ScheduleManager::GetCurrentScheduleValue(state, con.GCGenerateRateSchedPtr) *
    1811        4338 :                          (1.0 - state.dataContaminantBalance->ZoneAirGC(ZoneNum) / con.GCCutoffValue);
    1812             :             } else {
    1813           0 :                 GCGain = 0.0;
    1814             :             }
    1815        4338 :             con.GCGenRate = GCGain;
    1816             :         }
    1817             : 
    1818             :         // From decay model
    1819        9258 :         for (auto &con : state.dataContaminantBalance->ZoneContamGenericDecay) {
    1820        2169 :             int Sch = ScheduleManager::GetCurrentScheduleValue(state, con.GCEmiRateSchedPtr);
    1821        2169 :             if (Sch == 0.0 || state.dataGlobal->BeginEnvrnFlag || state.dataGlobal->WarmupFlag) {
    1822        1881 :                 con.GCTime = 0.0;
    1823             :             } else {
    1824         288 :                 con.GCTime += state.dataGlobal->TimeStepZoneSec;
    1825             :             }
    1826        2169 :             GCGain = con.GCInitEmiRate * Sch * std::exp(-con.GCTime / con.GCDelayTime);
    1827        2169 :             con.GCGenRate = GCGain;
    1828             :         }
    1829             : 
    1830             :         // From boudary layer diffusion
    1831        9258 :         for (auto &con : state.dataContaminantBalance->ZoneContamGenericBLDiff) {
    1832        2169 :             int SurfNum = con.SurfNum;
    1833        2169 :             int ZoneNum = state.dataSurface->Surface(SurfNum).Zone;
    1834             :             // Surface concentration level for the Boundary Layer Diffusion Controlled Model
    1835        2169 :             Real64 Cs = state.dataSurface->SurfGenericContam(SurfNum);
    1836        2169 :             Sch = ScheduleManager::GetCurrentScheduleValue(state, con.GCTranCoefSchedPtr);
    1837        2169 :             GCGain = con.GCTranCoef * Sch * state.dataSurface->Surface(SurfNum).Area * state.dataSurface->Surface(SurfNum).Multiplier *
    1838        2169 :                      (Cs / con.GCHenryCoef - state.dataContaminantBalance->ZoneAirGC(ZoneNum)) * 1.0e-6;
    1839        2169 :             con.GCGenRate = GCGain;
    1840             :             // Surface concentration level based on steady-state assumption
    1841        2169 :             state.dataSurface->SurfGenericContam(SurfNum) =
    1842        2169 :                 Cs - GCGain * 1.0e6 / state.dataSurface->Surface(SurfNum).Multiplier / state.dataSurface->Surface(SurfNum).Area;
    1843             :         }
    1844             : 
    1845             :         // From deposition velocity sink model
    1846        9258 :         for (auto &con : state.dataContaminantBalance->ZoneContamGenericDVS) {
    1847        2169 :             int SurfNum = con.SurfNum;
    1848        2169 :             int ZoneNum = state.dataSurface->Surface(SurfNum).Zone;
    1849        2169 :             Sch = ScheduleManager::GetCurrentScheduleValue(state, con.GCDepoVeloPtr);
    1850        2169 :             GCGain = -con.GCDepoVelo * state.dataSurface->Surface(SurfNum).Area * Sch * state.dataContaminantBalance->ZoneAirGC(ZoneNum) *
    1851        2169 :                      state.dataSurface->Surface(SurfNum).Multiplier * 1.0e-6;
    1852        2169 :             con.GCGenRate = GCGain;
    1853             :         }
    1854             : 
    1855             :         // From deposition rate sink model
    1856        9258 :         for (auto &con : state.dataContaminantBalance->ZoneContamGenericDRS) {
    1857        2169 :             int ZoneNum = con.ActualZoneNum;
    1858        2169 :             Sch = ScheduleManager::GetCurrentScheduleValue(state, con.GCDepoRatePtr);
    1859        2169 :             GCGain = -con.GCDepoRate * state.dataHeatBal->Zone(ZoneNum).Volume * Sch * state.dataContaminantBalance->ZoneAirGC(ZoneNum) * 1.0e-6;
    1860        2169 :             con.GCGenRate = GCGain;
    1861             :         }
    1862             :     }
    1863       41703 : }
    1864             : 
    1865       64209 : void PredictZoneContaminants(EnergyPlusData &state,
    1866             :                              bool const ShortenTimeStepSys,
    1867             :                              bool const UseZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
    1868             :                              Real64 const PriorTimeStep         // the old value for timestep length is passed for possible use in interpolating
    1869             : )
    1870             : {
    1871             : 
    1872             :     // SUBROUTINE INFORMATION:
    1873             :     //       AUTHOR         Lixing Gu
    1874             :     //       DATE WRITTEN   May 2010
    1875             : 
    1876             :     // PURPOSE OF THIS SUBROUTINE:
    1877             :     // This subroutine does the prediction step for contaminant control
    1878             : 
    1879             :     // METHODOLOGY EMPLOYED:
    1880             :     // This solves for the required outdoor airflow to achieve the desired contaminant setpoint in the Zone
    1881             : 
    1882             :     static constexpr std::string_view RoutineName("PredictZoneContaminants");
    1883             : 
    1884             :     Real64 A;                  // Coefficient of storage term in a zone balance equation
    1885             :     Real64 B;                  // Coefficient of variable term in a zone balance equation
    1886             :     Real64 C;                  // Coefficient of constnat term in a zone balance equation
    1887             :     Real64 LoadToCO2SetPoint;  // CO2 load at CO2 set point
    1888             :     Real64 ZoneAirCO2SetPoint; // Zone CO2 setpoint
    1889             :     Real64 LoadToGCSetPoint;   // Generic contaminant load at generic contaminant set point
    1890             :     Real64 ZoneAirGCSetPoint;  // Zone generic contaminant setpoint
    1891             :     Real64 GCGain;             // Zone generic contaminant internal load
    1892             : 
    1893             :     // Update zone CO2
    1894      457894 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1895      393685 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    1896             : 
    1897      393685 :         if (ShortenTimeStepSys) {
    1898             : 
    1899       45633 :             if (state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber > 0) { // roll back result for zone air node,
    1900       43713 :                 if (state.dataContaminantBalance->Contaminant.CO2Simulation)
    1901       42702 :                     state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber).CO2 =
    1902       42702 :                         state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum);
    1903       43713 :                 if (state.dataContaminantBalance->Contaminant.GenericContamSimulation)
    1904       35986 :                     state.dataLoopNodes->Node(state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber).GenContam =
    1905       35986 :                         state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum);
    1906             :             }
    1907             : 
    1908       45633 :             if (state.dataHVACGlobal->NumOfSysTimeSteps !=
    1909       45633 :                 state.dataHVACGlobal->NumOfSysTimeStepsLastZoneTimeStep) { // cannot reuse existing DS data, interpolate from zone time
    1910             : 
    1911       31814 :                 if (state.dataContaminantBalance->Contaminant.CO2Simulation)
    1912       31398 :                     ZoneTempPredictorCorrector::DownInterpolate4HistoryValues(PriorTimeStep,
    1913       31398 :                                                                               state.dataHVACGlobal->TimeStepSys,
    1914       31398 :                                                                               state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum),
    1915       31398 :                                                                               state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum),
    1916       31398 :                                                                               state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum),
    1917       31398 :                                                                               state.dataContaminantBalance->ZoneAirCO2(ZoneNum),
    1918       31398 :                                                                               state.dataContaminantBalance->DSCO2ZoneTimeMinus1(ZoneNum),
    1919       31398 :                                                                               state.dataContaminantBalance->DSCO2ZoneTimeMinus2(ZoneNum),
    1920       31398 :                                                                               state.dataContaminantBalance->DSCO2ZoneTimeMinus3(ZoneNum),
    1921       31398 :                                                                               state.dataContaminantBalance->DSCO2ZoneTimeMinus4(ZoneNum));
    1922       31814 :                 if (state.dataContaminantBalance->Contaminant.GenericContamSimulation)
    1923       29002 :                     ZoneTempPredictorCorrector::DownInterpolate4HistoryValues(PriorTimeStep,
    1924       29002 :                                                                               state.dataHVACGlobal->TimeStepSys,
    1925       29002 :                                                                               state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum),
    1926       29002 :                                                                               state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum),
    1927       29002 :                                                                               state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum),
    1928       29002 :                                                                               state.dataContaminantBalance->ZoneAirGC(ZoneNum),
    1929       29002 :                                                                               state.dataContaminantBalance->DSGCZoneTimeMinus1(ZoneNum),
    1930       29002 :                                                                               state.dataContaminantBalance->DSGCZoneTimeMinus2(ZoneNum),
    1931       29002 :                                                                               state.dataContaminantBalance->DSGCZoneTimeMinus3(ZoneNum),
    1932       29002 :                                                                               state.dataContaminantBalance->DSGCZoneTimeMinus4(ZoneNum));
    1933             : 
    1934             :             } else { // reuse history data in DS terms from last zone time step to preserve information that would be lost
    1935             :                      // do nothing because DS history would have been pushed prior and should be ready
    1936             :             }
    1937             :         }
    1938             :         // now update the variables actually used in the balance equations.
    1939      393685 :         if (UseZoneTimeStepHistory) {
    1940             : 
    1941      152943 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1942      144831 :                 state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum);
    1943      144831 :                 state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum);
    1944      144831 :                 state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum);
    1945             :             }
    1946      152943 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1947       55107 :                 state.dataContaminantBalance->GCZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum);
    1948       55107 :                 state.dataContaminantBalance->GCZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum);
    1949       55107 :                 state.dataContaminantBalance->GCZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum);
    1950             :             }
    1951             : 
    1952             :         } else { // use down-stepped history
    1953             : 
    1954      240742 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1955      236806 :                 state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus1(ZoneNum);
    1956      236806 :                 state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus2(ZoneNum);
    1957      236806 :                 state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus3(ZoneNum);
    1958             :             }
    1959      240742 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1960      214645 :                 state.dataContaminantBalance->GCZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus1(ZoneNum);
    1961      214645 :                 state.dataContaminantBalance->GCZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus2(ZoneNum);
    1962      214645 :                 state.dataContaminantBalance->GCZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus3(ZoneNum);
    1963             :             }
    1964             :         }
    1965             : 
    1966      393685 :         if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    1967           0 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1968           0 :                 if (ShortenTimeStepSys && state.dataHVACGlobal->TimeStepSys < state.dataGlobal->TimeStepZone) {
    1969           0 :                     if (state.dataHVACGlobal->PreviousTimeStep < state.dataGlobal->TimeStepZone) {
    1970           0 :                         state.dataContaminantBalance->ZoneCO21(ZoneNum) = state.dataContaminantBalance->ZoneCO2M2(ZoneNum);
    1971             :                     } else {
    1972           0 :                         state.dataContaminantBalance->ZoneCO21(ZoneNum) = state.dataContaminantBalance->ZoneCO2MX(ZoneNum);
    1973             :                     }
    1974           0 :                     state.dataHVACGlobal->ShortenTimeStepSysRoomAir = true;
    1975             :                 } else {
    1976           0 :                     state.dataContaminantBalance->ZoneCO21(ZoneNum) = state.dataContaminantBalance->ZoneAirCO2(ZoneNum);
    1977             :                 }
    1978             :             }
    1979           0 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1980           0 :                 if (ShortenTimeStepSys && state.dataHVACGlobal->TimeStepSys < state.dataGlobal->TimeStepZone) {
    1981           0 :                     if (state.dataHVACGlobal->PreviousTimeStep < state.dataGlobal->TimeStepZone) {
    1982           0 :                         state.dataContaminantBalance->ZoneGC1(ZoneNum) = state.dataContaminantBalance->ZoneGCM2(ZoneNum);
    1983             :                     } else {
    1984           0 :                         state.dataContaminantBalance->ZoneGC1(ZoneNum) = state.dataContaminantBalance->ZoneGCMX(ZoneNum);
    1985             :                     }
    1986           0 :                     state.dataHVACGlobal->ShortenTimeStepSysRoomAir = true;
    1987             :                 } else {
    1988           0 :                     state.dataContaminantBalance->ZoneGC1(ZoneNum) = state.dataContaminantBalance->ZoneAirGC(ZoneNum);
    1989             :                 }
    1990             :             }
    1991             :         }
    1992             : 
    1993      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1994             : 
    1995      381637 :             state.dataContaminantBalance->CO2PredictedRate(ZoneNum) = 0.0;
    1996      381637 :             LoadToCO2SetPoint = 0.0;
    1997      381637 :             state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP = 0.0;
    1998             : 
    1999             :             // Check to see if this is a "CO2 controlled zone"
    2000      381637 :             bool ControlledCO2ZoneFlag = false;
    2001             :             // Check all the controlled zones to see if it matches the zone simulated
    2002      534362 :             for (auto const &contaminantControlledZone : state.dataContaminantBalance->ContaminantControlledZone) {
    2003      211955 :                 if (contaminantControlledZone.ActualZoneNum == ZoneNum) {
    2004       59230 :                     if (ScheduleManager::GetCurrentScheduleValue(state, contaminantControlledZone.AvaiSchedPtr) > 0.0) {
    2005       59230 :                         ZoneAirCO2SetPoint = state.dataContaminantBalance->ZoneCO2SetPoint(contaminantControlledZone.ActualZoneNum);
    2006       59230 :                         if (contaminantControlledZone.EMSOverrideCO2SetPointOn) {
    2007           0 :                             ZoneAirCO2SetPoint = contaminantControlledZone.EMSOverrideCO2SetPointValue;
    2008             :                         }
    2009       59230 :                         ControlledCO2ZoneFlag = true;
    2010       59230 :                         break;
    2011             :                     }
    2012             :                 }
    2013             :             }
    2014      381637 :             if (!ControlledCO2ZoneFlag) {
    2015      364064 :                 for (auto const &contaminantControlledZone : state.dataContaminantBalance->ContaminantControlledZone) {
    2016       69573 :                     if (ScheduleManager::GetCurrentScheduleValue(state, contaminantControlledZone.AvaiSchedPtr) > 0.0) {
    2017       69573 :                         ZoneAirCO2SetPoint = state.dataContaminantBalance->ZoneCO2SetPoint(contaminantControlledZone.ActualZoneNum);
    2018       69573 :                         if (contaminantControlledZone.EMSOverrideCO2SetPointOn) {
    2019           0 :                             ZoneAirCO2SetPoint = contaminantControlledZone.EMSOverrideCO2SetPointValue;
    2020             :                         }
    2021       69573 :                         if (contaminantControlledZone.NumOfZones >= 1) {
    2022       69573 :                             if (contaminantControlledZone.ActualZoneNum != ZoneNum) {
    2023      294443 :                                 for (int I = 1; I <= contaminantControlledZone.NumOfZones; ++I) {
    2024      252786 :                                     if (contaminantControlledZone.ControlZoneNum(I) == ZoneNum) {
    2025       27916 :                                         ControlledCO2ZoneFlag = true;
    2026       27916 :                                         break;
    2027             :                                     }
    2028             :                                 }
    2029       69573 :                                 if (ControlledCO2ZoneFlag) break;
    2030             :                             } else {
    2031           0 :                                 ControlledCO2ZoneFlag = true;
    2032           0 :                                 break;
    2033             :                             }
    2034             :                         }
    2035             :                     }
    2036             :                 }
    2037             :             } // CO2ControlledZoneNum
    2038             : 
    2039      381637 :             if (ControlledCO2ZoneFlag) {
    2040       87146 :                 Real64 RhoAir = PsyRhoAirFnPbTdbW(state,
    2041       87146 :                                                   state.dataEnvrn->OutBaroPress,
    2042             :                                                   thisZoneHB.ZT,
    2043             :                                                   thisZoneHB.airHumRat,
    2044             :                                                   RoutineName); // The density of air
    2045             : 
    2046             :                 // Calculate Co2 from infiltration + humidity added from latent load to determine system added/subtracted moisture.
    2047       87146 :                 Real64 CO2Gain = state.dataContaminantBalance->ZoneCO2Gain(ZoneNum) * RhoAir * 1.0e6;
    2048             : 
    2049       87146 :                 Real64 SysTimeStepInSeconds = Constant::SecInHour * state.dataHVACGlobal->TimeStepSys;
    2050             : 
    2051             :                 // Calculate the coefficients for the 3rd Order derivative for final
    2052             :                 // zone CO2.  The A, B, C coefficients are analogous to the CO2 balance.
    2053             :                 // Assume that the system will have flow
    2054       87146 :                 auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    2055      162961 :                 if (state.afn->multizone_always_simulated ||
    2056       75815 :                     (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    2057           0 :                      state.afn->AirflowNetworkFanActivated)) {
    2058             :                     // Multizone airflow calculated in AirflowNetwork
    2059       11331 :                     B = CO2Gain + state.afn->exchangeData(ZoneNum).SumMHrCO + state.afn->exchangeData(ZoneNum).SumMMHrCO;
    2060       11331 :                     A = state.afn->exchangeData(ZoneNum).SumMHr + state.afn->exchangeData(ZoneNum).SumMMHr;
    2061             :                 } else {
    2062      151630 :                     B = CO2Gain +
    2063       75815 :                         ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorCO2) +
    2064       75815 :                         state.dataContaminantBalance->MixingMassFlowCO2(ZoneNum) + thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorCO2;
    2065       75815 :                     A = thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    2066             :                 }
    2067       87146 :                 C = RhoAir * state.dataHeatBal->Zone(ZoneNum).Volume * state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpCO2 / SysTimeStepInSeconds;
    2068             : 
    2069             :                 // Use a 3rd Order derivative to predict zone moisture addition or removal and
    2070             :                 // smooth the changes using the zone air capacitance.  Positive values of CO2 Load means that
    2071             :                 // this amount of CO2 must be added to the zone to reach the setpoint.  Negative values represent
    2072             :                 // the amount of CO2 that must be removed by the system.
    2073       87146 :                 switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    2074       87146 :                 case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    2075      174292 :                     LoadToCO2SetPoint = ((11.0 / 6.0) * C + A) * ZoneAirCO2SetPoint -
    2076       87146 :                                         (B + C * (3.0 * state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) -
    2077       87146 :                                                   (3.0 / 2.0) * state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) +
    2078       87146 :                                                   (1.0 / 3.0) * state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum)));
    2079             :                     // Exact solution
    2080       87146 :                 } break;
    2081           0 :                 case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    2082           0 :                     if (A == 0.0) { // B=0
    2083           0 :                         LoadToCO2SetPoint = C * (ZoneAirCO2SetPoint - state.dataContaminantBalance->ZoneCO21(ZoneNum)) - B;
    2084             :                     } else {
    2085           0 :                         LoadToCO2SetPoint =
    2086           0 :                             A * (ZoneAirCO2SetPoint - state.dataContaminantBalance->ZoneCO21(ZoneNum) * std::exp(min(700.0, -A / C))) /
    2087           0 :                                 (1.0 - std::exp(min(700.0, -A / C))) -
    2088             :                             B;
    2089             :                     }
    2090           0 :                 } break;
    2091           0 :                 case DataHeatBalance::SolutionAlgo::EulerMethod: {
    2092           0 :                     LoadToCO2SetPoint = C * (ZoneAirCO2SetPoint - state.dataContaminantBalance->ZoneCO21(ZoneNum)) + A * ZoneAirCO2SetPoint - B;
    2093           0 :                 } break;
    2094           0 :                 default:
    2095           0 :                     break;
    2096             :                 }
    2097       87146 :                 if (ZoneAirCO2SetPoint > state.dataContaminantBalance->OutdoorCO2 && LoadToCO2SetPoint < 0.0) {
    2098       13137 :                     state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP =
    2099       13137 :                         LoadToCO2SetPoint / (state.dataContaminantBalance->OutdoorCO2 - ZoneAirCO2SetPoint);
    2100             :                 }
    2101             :             }
    2102             : 
    2103             :             // Apply the Zone Multiplier to the total zone moisture load
    2104      381637 :             state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP *=
    2105      381637 :                 state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier;
    2106      381637 :             state.dataContaminantBalance->CO2PredictedRate(ZoneNum) = state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToCO2SP;
    2107             :         }
    2108             : 
    2109      393685 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2110             : 
    2111      269752 :             state.dataContaminantBalance->GCPredictedRate(ZoneNum) = 0.0;
    2112      269752 :             LoadToGCSetPoint = 0.0;
    2113      269752 :             state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToGCSP = 0.0;
    2114             : 
    2115             :             // Check to see if this is a "GC controlled zone"
    2116      269752 :             bool ControlledGCZoneFlag = false;
    2117             :             // Check all the controlled zones to see if it matches the zone simulated
    2118      275328 :             for (auto const &contaminantControlledZone : state.dataContaminantBalance->ContaminantControlledZone) {
    2119        8364 :                 if (contaminantControlledZone.ActualZoneNum == ZoneNum) {
    2120        2788 :                     if (ScheduleManager::GetCurrentScheduleValue(state, contaminantControlledZone.AvaiSchedPtr) > 0.0) {
    2121        2788 :                         ZoneAirGCSetPoint = state.dataContaminantBalance->ZoneGCSetPoint(contaminantControlledZone.ActualZoneNum);
    2122        2788 :                         if (contaminantControlledZone.EMSOverrideCO2SetPointOn) {
    2123           0 :                             ZoneAirGCSetPoint = contaminantControlledZone.EMSOverrideGCSetPointValue;
    2124             :                         }
    2125        2788 :                         ControlledGCZoneFlag = true;
    2126        2788 :                         break;
    2127             :                     }
    2128             :                 }
    2129             :             }
    2130      269752 :             if (!ControlledGCZoneFlag) {
    2131      266964 :                 for (auto const &contaminantControlledZone : state.dataContaminantBalance->ContaminantControlledZone) {
    2132        5576 :                     if (ScheduleManager::GetCurrentScheduleValue(state, contaminantControlledZone.AvaiSchedPtr) > 0.0) {
    2133        5576 :                         ZoneAirGCSetPoint = state.dataContaminantBalance->ZoneGCSetPoint(contaminantControlledZone.ActualZoneNum);
    2134        5576 :                         if (contaminantControlledZone.EMSOverrideCO2SetPointOn) {
    2135           0 :                             ZoneAirGCSetPoint = contaminantControlledZone.EMSOverrideGCSetPointValue;
    2136             :                         }
    2137        5576 :                         if (contaminantControlledZone.NumOfZones >= 1) {
    2138        5576 :                             if (contaminantControlledZone.ActualZoneNum != ZoneNum) {
    2139       11152 :                                 for (int I = 1; I <= contaminantControlledZone.NumOfZones; ++I) {
    2140       11152 :                                     if (contaminantControlledZone.ControlZoneNum(I) == ZoneNum) {
    2141        5576 :                                         ControlledGCZoneFlag = true;
    2142        5576 :                                         break;
    2143             :                                     }
    2144             :                                 }
    2145        5576 :                                 if (ControlledGCZoneFlag) break;
    2146             :                             } else {
    2147           0 :                                 ControlledGCZoneFlag = true;
    2148           0 :                                 break;
    2149             :                             }
    2150             :                         }
    2151             :                     }
    2152             :                 }
    2153             :             }
    2154             : 
    2155      269752 :             if (ControlledGCZoneFlag) {
    2156             :                 // The density of air
    2157        8364 :                 Real64 RhoAir = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.ZT, thisZoneHB.airHumRat, RoutineName);
    2158             : 
    2159             :                 // Calculate generic contaminant from infiltration + humidity added from latent load
    2160             :                 // to determine system added/subtracted moisture.
    2161        8364 :                 GCGain = state.dataContaminantBalance->ZoneGCGain(ZoneNum) * RhoAir * 1.0e6;
    2162             : 
    2163        8364 :                 Real64 SysTimeStepInSeconds = Constant::SecInHour * state.dataHVACGlobal->TimeStepSys;
    2164             : 
    2165             :                 // Calculate the coefficients for the 3rd Order derivative for final
    2166             :                 // zone GC.  The A, B, C coefficients are analogous to the GC balance.
    2167             :                 // Assume that the system will have flow
    2168        8364 :                 auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    2169       16728 :                 if (state.afn->multizone_always_simulated ||
    2170        8364 :                     (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    2171           0 :                      state.afn->AirflowNetworkFanActivated)) {
    2172             :                     // Multizone airflow calculated in AirflowNetwork
    2173           0 :                     B = GCGain + state.afn->exchangeData(ZoneNum).SumMHrGC + state.afn->exchangeData(ZoneNum).SumMMHrGC;
    2174           0 :                     A = state.afn->exchangeData(ZoneNum).SumMHr + state.afn->exchangeData(ZoneNum).SumMMHr;
    2175             :                 } else {
    2176       16728 :                     B = GCGain +
    2177        8364 :                         ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorGC) +
    2178        8364 :                         state.dataContaminantBalance->MixingMassFlowGC(ZoneNum) + thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorGC;
    2179        8364 :                     A = thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    2180             :                 }
    2181        8364 :                 C = RhoAir * state.dataHeatBal->Zone(ZoneNum).Volume * state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpGenContam /
    2182             :                     SysTimeStepInSeconds;
    2183             : 
    2184             :                 // Use a 3rd Order derivative to predict zone moisture addition or removal and
    2185             :                 // smooth the changes using the zone air capacitance.  Positive values of GC Load means that
    2186             :                 // this amount of GC must be added to the zone to reach the setpoint.  Negative values represent
    2187             :                 // the amount of GC that must be removed by the system.
    2188        8364 :                 switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    2189        8364 :                 case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    2190       16728 :                     LoadToGCSetPoint = ((11.0 / 6.0) * C + A) * ZoneAirGCSetPoint -
    2191        8364 :                                        (B + C * (3.0 * state.dataContaminantBalance->GCZoneTimeMinus1Temp(ZoneNum) -
    2192        8364 :                                                  (3.0 / 2.0) * state.dataContaminantBalance->GCZoneTimeMinus2Temp(ZoneNum) +
    2193        8364 :                                                  (1.0 / 3.0) * state.dataContaminantBalance->GCZoneTimeMinus3Temp(ZoneNum)));
    2194             :                     // Exact solution
    2195        8364 :                 } break;
    2196           0 :                 case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    2197           0 :                     if (A == 0.0) { // B=0
    2198           0 :                         LoadToGCSetPoint = C * (ZoneAirGCSetPoint - state.dataContaminantBalance->ZoneGC1(ZoneNum)) - B;
    2199             :                     } else {
    2200           0 :                         LoadToGCSetPoint = A * (ZoneAirGCSetPoint - state.dataContaminantBalance->ZoneGC1(ZoneNum) * std::exp(min(700.0, -A / C))) /
    2201           0 :                                                (1.0 - std::exp(min(700.0, -A / C))) -
    2202             :                                            B;
    2203             :                     }
    2204           0 :                 } break;
    2205           0 :                 case DataHeatBalance::SolutionAlgo::EulerMethod: {
    2206           0 :                     LoadToGCSetPoint = C * (ZoneAirGCSetPoint - state.dataContaminantBalance->ZoneGC1(ZoneNum)) + A * ZoneAirGCSetPoint - B;
    2207           0 :                 } break;
    2208           0 :                 default:
    2209           0 :                     break;
    2210             :                 }
    2211        8364 :                 if (ZoneAirGCSetPoint > state.dataContaminantBalance->OutdoorGC && LoadToGCSetPoint < 0.0) {
    2212        5986 :                     state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToGCSP =
    2213        5986 :                         LoadToGCSetPoint / (state.dataContaminantBalance->OutdoorGC - ZoneAirGCSetPoint);
    2214             :                 }
    2215             :             }
    2216             : 
    2217             :             // Apply the Zone Multiplier to the total zone moisture load
    2218      269752 :             state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToGCSP *=
    2219      269752 :                 state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier;
    2220      269752 :             state.dataContaminantBalance->GCPredictedRate(ZoneNum) = state.dataContaminantBalance->ZoneSysContDemand(ZoneNum).OutputRequiredToGCSP;
    2221             :         }
    2222             :     }
    2223       64209 : }
    2224             : 
    2225       41703 : void PushZoneTimestepHistories(EnergyPlusData &state)
    2226             : {
    2227             : 
    2228             :     // SUBROUTINE INFORMATION:
    2229             :     //       AUTHOR         Lixing Gu
    2230             :     //       DATE WRITTEN   July, 2010
    2231             : 
    2232             :     // PURPOSE OF THIS SUBROUTINE:
    2233             :     // Push the temperature and humidity ratio histories
    2234             :     // This subroutine is modified from PushZoneTimestepHistories in ZoneTempPredictorCorrector module
    2235             : 
    2236      194646 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2237      152943 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2238      144831 :             state.dataContaminantBalance->CO2ZoneTimeMinus4(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum);
    2239      144831 :             state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum);
    2240      144831 :             state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum);
    2241      144831 :             state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum) =
    2242      144831 :                 state.dataContaminantBalance->ZoneAirCO2Avg(ZoneNum); // using average for whole zone time step.
    2243      144831 :             state.dataContaminantBalance->ZoneAirCO2(ZoneNum) = state.dataContaminantBalance->ZoneAirCO2Temp(ZoneNum);
    2244             : 
    2245      144831 :             if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    2246           0 :                 state.dataContaminantBalance->ZoneCO2M2(ZoneNum) = state.dataContaminantBalance->ZoneCO2MX(ZoneNum);
    2247           0 :                 state.dataContaminantBalance->ZoneCO2MX(ZoneNum) =
    2248           0 :                     state.dataContaminantBalance->ZoneAirCO2Avg(ZoneNum); // using average for whole zone time step.
    2249             :             }
    2250             :         }
    2251             : 
    2252      152943 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2253       55107 :             state.dataContaminantBalance->GCZoneTimeMinus4(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum);
    2254       55107 :             state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum);
    2255       55107 :             state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum);
    2256       55107 :             state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum) =
    2257       55107 :                 state.dataContaminantBalance->ZoneAirGCAvg(ZoneNum); // using average for whole zone time step.
    2258       55107 :             state.dataContaminantBalance->ZoneAirGC(ZoneNum) = state.dataContaminantBalance->ZoneAirGCTemp(ZoneNum);
    2259             : 
    2260       55107 :             if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    2261           0 :                 state.dataContaminantBalance->ZoneGCM2(ZoneNum) = state.dataContaminantBalance->ZoneGCMX(ZoneNum);
    2262           0 :                 state.dataContaminantBalance->ZoneGCMX(ZoneNum) =
    2263           0 :                     state.dataContaminantBalance->ZoneAirGCAvg(ZoneNum); // using average for whole zone time step.
    2264             :             }
    2265             :         }
    2266             :     }
    2267       41703 : }
    2268             : 
    2269       22506 : void PushSystemTimestepHistories(EnergyPlusData &state)
    2270             : {
    2271             : 
    2272             :     // SUBROUTINE INFORMATION:
    2273             :     //       AUTHOR         Lixing Gu
    2274             :     //       DATE WRITTEN   July, 2010
    2275             : 
    2276             :     // PURPOSE OF THIS SUBROUTINE:
    2277             :     // push histories back in time
    2278             :     // This subroutine is modified from PushSystemTimestepHistories in ZoneTempPredictorCorrector module
    2279             : 
    2280      263248 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2281      240742 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2282      236806 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus4(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus3(ZoneNum);
    2283      236806 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus3(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus2(ZoneNum);
    2284      236806 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus2(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus1(ZoneNum);
    2285      236806 :             state.dataContaminantBalance->DSCO2ZoneTimeMinus1(ZoneNum) = state.dataContaminantBalance->ZoneAirCO2(ZoneNum);
    2286             :         }
    2287      240742 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2288      214645 :             state.dataContaminantBalance->DSGCZoneTimeMinus4(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus3(ZoneNum);
    2289      214645 :             state.dataContaminantBalance->DSGCZoneTimeMinus3(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus2(ZoneNum);
    2290      214645 :             state.dataContaminantBalance->DSGCZoneTimeMinus2(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus1(ZoneNum);
    2291      214645 :             state.dataContaminantBalance->DSGCZoneTimeMinus1(ZoneNum) = state.dataContaminantBalance->ZoneAirGC(ZoneNum);
    2292             :         }
    2293             :     }
    2294             : 
    2295       22506 :     if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
    2296           0 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2297           0 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2298           0 :                 state.dataContaminantBalance->ZoneCO2M2(ZoneNum) = state.dataContaminantBalance->ZoneCO2MX(ZoneNum);
    2299           0 :                 state.dataContaminantBalance->ZoneCO2MX(ZoneNum) =
    2300           0 :                     state.dataContaminantBalance->ZoneAirCO2Temp(ZoneNum); // using average for whole zone time step.
    2301             :             }
    2302           0 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2303           0 :                 state.dataContaminantBalance->ZoneGCM2(ZoneNum) = state.dataContaminantBalance->ZoneGCMX(ZoneNum);
    2304           0 :                 state.dataContaminantBalance->ZoneGCMX(ZoneNum) =
    2305           0 :                     state.dataContaminantBalance->ZoneAirGCTemp(ZoneNum); // using average for whole zone time step.
    2306             :             }
    2307             :         }
    2308             :     }
    2309       22506 : }
    2310             : 
    2311           0 : void RevertZoneTimestepHistories(EnergyPlusData &state)
    2312             : {
    2313             : 
    2314             :     // SUBROUTINE INFORMATION:
    2315             :     //       AUTHOR         Lixing Gu
    2316             :     //       DATE WRITTEN   July, 2010
    2317             : 
    2318             :     // PURPOSE OF THIS SUBROUTINE:
    2319             :     // rewind histories to undo inadvertent pushing
    2320             :     // This subroutine is modified from RevertZoneTimestepHistories in ZoneTempPredictorCorrector module
    2321             : 
    2322           0 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2323           0 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2324           0 :             state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum);
    2325           0 :             state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum);
    2326           0 :             state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus4(ZoneNum);
    2327             :         }
    2328           0 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2329           0 :             state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum);
    2330           0 :             state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum);
    2331           0 :             state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus4(ZoneNum);
    2332             :         }
    2333             :     }
    2334           0 : }
    2335             : 
    2336         600 : void InverseModelCO2(EnergyPlusData &state,
    2337             :                      int const ZoneNum,           // Zone number
    2338             :                      Real64 &CO2Gain,             // Zone total CO2 gain
    2339             :                      Real64 &CO2GainExceptPeople, // ZOne total CO2 gain from sources except for people
    2340             :                      Real64 &ZoneMassFlowRate,    // Zone air mass flow rate
    2341             :                      Real64 &CO2MassFlowRate,     // Zone air CO2 mass flow rate
    2342             :                      Real64 &RhoAir               // Air density
    2343             : )
    2344             : {
    2345             :     // SUBROUTINE INFORMATION:
    2346             :     //       AUTHOR         Han Li
    2347             :     //       DATE WRITTEN   February 2019
    2348             : 
    2349             :     // PURPOSE OF THIS SUBROUTINE:
    2350             :     // This subroutine inversely solve infiltration airflow rate or people count with zone air CO2 concentration measurements.
    2351             : 
    2352         600 :     Real64 AA(0.0);
    2353         600 :     Real64 BB(0.0);
    2354         600 :     Real64 M_inf(0.0); // Reversely solved infiltration mass flow rate
    2355             : 
    2356         600 :     Real64 SysTimeStepInSeconds(0.0);
    2357         600 :     SysTimeStepInSeconds = Constant::SecInHour * state.dataHVACGlobal->TimeStepSys;
    2358             : 
    2359         600 :     state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration =
    2360         600 :         ScheduleManager::GetCurrentScheduleValue(state, state.dataHybridModel->HybridModelZone(ZoneNum).ZoneMeasuredCO2ConcentrationSchedulePtr);
    2361             : 
    2362        1200 :     if (state.dataEnvrn->DayOfYear >= state.dataHybridModel->HybridModelZone(ZoneNum).HybridStartDayOfYear &&
    2363         600 :         state.dataEnvrn->DayOfYear <= state.dataHybridModel->HybridModelZone(ZoneNum).HybridEndDayOfYear) {
    2364         600 :         state.dataContaminantBalance->ZoneAirCO2(ZoneNum) = state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration;
    2365             : 
    2366         600 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    2367         600 :         if (state.dataHybridModel->HybridModelZone(ZoneNum).InfiltrationCalc_C && state.dataHVACGlobal->UseZoneTimeStepHistory) {
    2368             :             static constexpr std::string_view RoutineNameInfiltration("CalcAirFlowSimple:Infiltration");
    2369             :             // Conditionally calculate the CO2-dependent and CO2-independent terms.
    2370         288 :             if (state.dataHybridModel->HybridModelZone(ZoneNum).IncludeSystemSupplyParameters) {
    2371           0 :                 state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirFlowRate = ScheduleManager::GetCurrentScheduleValue(
    2372           0 :                     state, state.dataHybridModel->HybridModelZone(ZoneNum).ZoneSupplyAirMassFlowRateSchedulePtr);
    2373           0 :                 state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirCO2Concentration = ScheduleManager::GetCurrentScheduleValue(
    2374           0 :                     state, state.dataHybridModel->HybridModelZone(ZoneNum).ZoneSupplyAirCO2ConcentrationSchedulePtr);
    2375             : 
    2376           0 :                 Real64 SumSysM_HM = state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirFlowRate;
    2377           0 :                 Real64 SumSysMxCO2_HM = state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirFlowRate *
    2378           0 :                                         state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirCO2Concentration;
    2379             : 
    2380           0 :                 AA = SumSysM_HM + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    2381           0 :                 BB = SumSysMxCO2_HM + CO2Gain +
    2382           0 :                      ((thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorCO2) +
    2383           0 :                      state.dataContaminantBalance->MixingMassFlowCO2(ZoneNum) + thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorCO2;
    2384             : 
    2385             :             } else {
    2386         288 :                 AA = thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
    2387         288 :                 BB = CO2Gain + ((thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorCO2) +
    2388         288 :                      state.dataContaminantBalance->MixingMassFlowCO2(ZoneNum) + thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorCO2;
    2389             :             }
    2390             : 
    2391         288 :             Real64 CC = RhoAir * state.dataHeatBal->Zone(ZoneNum).Volume * state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpCO2 / SysTimeStepInSeconds;
    2392         288 :             Real64 DD = (3.0 * state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) -
    2393         288 :                          (3.0 / 2.0) * state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) +
    2394         288 :                          (1.0 / 3.0) * state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum));
    2395             : 
    2396         288 :             Real64 delta_CO2 = (state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration - state.dataContaminantBalance->OutdoorCO2) / 1000;
    2397         288 :             Real64 CpAir = PsyCpAirFnW(state.dataEnvrn->OutHumRat);
    2398         288 :             Real64 AirDensity = PsyRhoAirFnPbTdbW(state,
    2399         288 :                                                   state.dataEnvrn->OutBaroPress,
    2400         288 :                                                   state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp,
    2401         288 :                                                   state.dataEnvrn->OutHumRat,
    2402             :                                                   RoutineNameInfiltration);
    2403             : 
    2404         288 :             if (state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration == state.dataContaminantBalance->OutdoorCO2) {
    2405           0 :                 M_inf = 0.0;
    2406             :             } else {
    2407         288 :                 M_inf = (CC * DD + BB - ((11.0 / 6.0) * CC + AA) * state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration) / delta_CO2;
    2408             :             }
    2409             : 
    2410             :             // Add threshold for air change rate
    2411         288 :             Real64 ACH_inf = max(0.0, min(10.0, M_inf / (CpAir * AirDensity / Constant::SecInHour * state.dataHeatBal->Zone(ZoneNum).Volume)));
    2412         288 :             M_inf = ACH_inf * state.dataHeatBal->Zone(ZoneNum).Volume * AirDensity / Constant::SecInHour;
    2413         288 :             state.dataHeatBal->Zone(ZoneNum).MCPIHM = M_inf;
    2414         288 :             state.dataHeatBal->Zone(ZoneNum).InfilOAAirChangeRateHM = ACH_inf;
    2415             :         }
    2416             : 
    2417             :         // Hybrid Model calculate people count
    2418         600 :         if (state.dataHybridModel->HybridModelZone(ZoneNum).PeopleCountCalc_C && state.dataHVACGlobal->UseZoneTimeStepHistory) {
    2419         288 :             state.dataHeatBal->Zone(ZoneNum).ZonePeopleActivityLevel =
    2420         288 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataHybridModel->HybridModelZone(ZoneNum).ZonePeopleActivityLevelSchedulePtr);
    2421             :             Real64 ActivityLevel =
    2422         288 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataHybridModel->HybridModelZone(ZoneNum).ZonePeopleActivityLevelSchedulePtr);
    2423             :             Real64 CO2GenRate =
    2424         288 :                 ScheduleManager::GetCurrentScheduleValue(state, state.dataHybridModel->HybridModelZone(ZoneNum).ZonePeopleCO2GenRateSchedulePtr);
    2425         288 :             if (ActivityLevel <= 0.0) {
    2426           0 :                 ActivityLevel = 130.0; // 130.0 is the default people activity level [W]
    2427             :             }
    2428         288 :             if (CO2GenRate <= 0.0) {
    2429           0 :                 CO2GenRate = 0.0000000382; // 0.0000000382 is the default CO2, generation rate [m3/(s*W)]
    2430             :             }
    2431             : 
    2432             :             // Conditionally calculate the CO2-dependent and CO2-independent terms.
    2433         288 :             if (state.dataHybridModel->HybridModelZone(ZoneNum).IncludeSystemSupplyParameters) {
    2434         288 :                 state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirFlowRate = ScheduleManager::GetCurrentScheduleValue(
    2435         288 :                     state, state.dataHybridModel->HybridModelZone(ZoneNum).ZoneSupplyAirMassFlowRateSchedulePtr);
    2436         288 :                 state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirCO2Concentration = ScheduleManager::GetCurrentScheduleValue(
    2437         288 :                     state, state.dataHybridModel->HybridModelZone(ZoneNum).ZoneSupplyAirCO2ConcentrationSchedulePtr);
    2438             : 
    2439         288 :                 Real64 SumSysM_HM = state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirFlowRate;
    2440         288 :                 Real64 SumSysMxCO2_HM = state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirFlowRate *
    2441         288 :                                         state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredSupplyAirCO2Concentration;
    2442             : 
    2443         288 :                 AA = SumSysM_HM + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone +
    2444         288 :                      thisZoneHB.MDotOA;
    2445         864 :                 BB = CO2GainExceptPeople +
    2446         288 :                      ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorCO2) +
    2447         288 :                      (SumSysMxCO2_HM) + state.dataContaminantBalance->MixingMassFlowCO2(ZoneNum) +
    2448         288 :                      thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorCO2;
    2449             : 
    2450             :             } else {
    2451           0 :                 AA = ZoneMassFlowRate + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone +
    2452           0 :                      thisZoneHB.MDotOA;
    2453           0 :                 BB = CO2GainExceptPeople +
    2454           0 :                      ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorCO2) +
    2455           0 :                      (CO2MassFlowRate) + state.dataContaminantBalance->MixingMassFlowCO2(ZoneNum) +
    2456           0 :                      thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorCO2;
    2457             :             }
    2458             : 
    2459         288 :             Real64 CC = RhoAir * state.dataHeatBal->Zone(ZoneNum).Volume * state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpCO2 / SysTimeStepInSeconds;
    2460         288 :             Real64 DD = (3.0 * state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) -
    2461         288 :                          (3.0 / 2.0) * state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) +
    2462         288 :                          (1.0 / 3.0) * state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum));
    2463             : 
    2464             :             Real64 CO2GainPeople =
    2465         288 :                 (((11.0 / 6.0) * CC + AA) * state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration - BB - CC * DD) / (1000000 * RhoAir);
    2466             : 
    2467             :             // Make sure the results are reasonable
    2468         288 :             Real64 UpperBound = CO2Gain / (1000000 * RhoAir * CO2GenRate * ActivityLevel);
    2469         288 :             Real64 NumPeople = min(UpperBound, CO2GainPeople / (CO2GenRate * ActivityLevel));
    2470             : 
    2471         288 :             NumPeople = floor(NumPeople * 100.00 + 0.5) / 100.00;
    2472         288 :             if (NumPeople < 0.05) {
    2473         288 :                 NumPeople = 0;
    2474             :             }
    2475         288 :             state.dataHeatBal->Zone(ZoneNum).NumOccHM = NumPeople;
    2476             :         }
    2477             :     }
    2478             : 
    2479             :     // Update zone humidity ratio in the previous steps
    2480         600 :     state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum);
    2481         600 :     state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum);
    2482         600 :     state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) = state.dataHeatBal->Zone(ZoneNum).ZoneMeasuredCO2Concentration;
    2483         600 : }
    2484             : 
    2485       64209 : void CorrectZoneContaminants(EnergyPlusData &state,
    2486             :                              bool const UseZoneTimeStepHistory // if true then use zone timestep history, if false use system time step history
    2487             : )
    2488             : {
    2489             : 
    2490             :     // SUBROUTINE INFORMATION:
    2491             :     //       AUTHOR         Lixing Gu
    2492             :     //       DATE WRITTEN   July, 2010
    2493             : 
    2494             :     // PURPOSE OF THIS SUBROUTINE:
    2495             :     // This subroutine updates the zone contaminants.
    2496             :     // This subroutine is modified from CorrectZoneHumRat in ZoneTempPredictorCorrector module
    2497             : 
    2498             :     // REFERENCES:
    2499             :     // Routine FinalZnCalcs - FINAL ZONE CALCULATIONS, authored by Dale Herron for BLAST.
    2500             : 
    2501             :     static constexpr std::string_view RoutineName("CorrectZoneContaminants");
    2502             : 
    2503             :     Real64 CO2Gain;             // Zone CO2 internal gain
    2504             :     Real64 CO2GainExceptPeople; // Added for hybrid model, Zone CO2 internal gain
    2505             :     Real64 GCGain;              // Zone generic contaminant internal gain
    2506             :     Real64 A;
    2507             :     Real64 B;
    2508             :     Real64 C;
    2509             : 
    2510             :     // Update zone CO2
    2511      457894 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2512             : 
    2513      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2514      381637 :             state.dataContaminantBalance->AZ(ZoneNum) = 0.0;
    2515      381637 :             state.dataContaminantBalance->BZ(ZoneNum) = 0.0;
    2516      381637 :             state.dataContaminantBalance->CZ(ZoneNum) = 0.0;
    2517             :         }
    2518      393685 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2519      269752 :             state.dataContaminantBalance->AZGC(ZoneNum) = 0.0;
    2520      269752 :             state.dataContaminantBalance->BZGC(ZoneNum) = 0.0;
    2521      269752 :             state.dataContaminantBalance->CZGC(ZoneNum) = 0.0;
    2522             :         }
    2523             : 
    2524             :         // update the variables actually used in the balance equations.
    2525      393685 :         if (!UseZoneTimeStepHistory) {
    2526      240742 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2527      236806 :                 state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus1(ZoneNum);
    2528      236806 :                 state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus2(ZoneNum);
    2529      236806 :                 state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->DSCO2ZoneTimeMinus3(ZoneNum);
    2530             :             }
    2531      240742 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2532      214645 :                 state.dataContaminantBalance->GCZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus1(ZoneNum);
    2533      214645 :                 state.dataContaminantBalance->GCZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus2(ZoneNum);
    2534      214645 :                 state.dataContaminantBalance->GCZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->DSGCZoneTimeMinus3(ZoneNum);
    2535             :             }
    2536             :         } else {
    2537      152943 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2538      144831 :                 state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus1(ZoneNum);
    2539      144831 :                 state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus2(ZoneNum);
    2540      144831 :                 state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->CO2ZoneTimeMinus3(ZoneNum);
    2541             :             }
    2542      152943 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2543       55107 :                 state.dataContaminantBalance->GCZoneTimeMinus1Temp(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus1(ZoneNum);
    2544       55107 :                 state.dataContaminantBalance->GCZoneTimeMinus2Temp(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus2(ZoneNum);
    2545       55107 :                 state.dataContaminantBalance->GCZoneTimeMinus3Temp(ZoneNum) = state.dataContaminantBalance->GCZoneTimeMinus3(ZoneNum);
    2546             :             }
    2547             :         }
    2548             : 
    2549             :         // Start to calculate zone CO2 and genric contaminant levels
    2550      393685 :         Real64 CO2MassFlowRate = 0.0;
    2551      393685 :         Real64 GCMassFlowRate = 0.0;
    2552      393685 :         Real64 ZoneMassFlowRate = 0.0;
    2553      393685 :         int ZoneMult = state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier;
    2554             : 
    2555             :         // Check to see if this is a controlled zone
    2556      393685 :         const bool ControlledZoneAirFlag = state.dataHeatBal->Zone(ZoneNum).IsControlled;
    2557             : 
    2558             :         // Check to see if this is a plenum zone
    2559      393685 :         bool ZoneRetPlenumAirFlag = false;
    2560      393685 :         int ZoneRetPlenumNum = 0;
    2561      393685 :         for (ZoneRetPlenumNum = 1; ZoneRetPlenumNum <= state.dataZonePlenum->NumZoneReturnPlenums; ++ZoneRetPlenumNum) {
    2562           0 :             if (state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum).ActualZoneNum != ZoneNum) continue;
    2563           0 :             ZoneRetPlenumAirFlag = true;
    2564           0 :             break;
    2565             :         }
    2566      393685 :         bool ZoneSupPlenumAirFlag = false;
    2567      393685 :         int ZoneSupPlenumNum = 0;
    2568      393685 :         for (ZoneSupPlenumNum = 1; ZoneSupPlenumNum <= state.dataZonePlenum->NumZoneSupplyPlenums; ++ZoneSupPlenumNum) {
    2569           0 :             if (state.dataZonePlenum->ZoneSupPlenCond(ZoneSupPlenumNum).ActualZoneNum != ZoneNum) continue;
    2570           0 :             ZoneSupPlenumAirFlag = true;
    2571           0 :             break;
    2572             :         }
    2573             : 
    2574      393685 :         if (ControlledZoneAirFlag) { // If there is system flow then calculate the flow rates
    2575             : 
    2576             :             // Calculate moisture flow rate into each zone
    2577      622608 :             for (int NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumInletNodes; ++NodeNum) {
    2578      257874 :                 auto &node = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneNum).InletNode(NodeNum));
    2579      257874 :                 if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2580      248838 :                     CO2MassFlowRate += (node.MassFlowRate * node.CO2) / ZoneMult;
    2581             :                 }
    2582      257874 :                 if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2583      159880 :                     GCMassFlowRate += (node.MassFlowRate * node.GenContam) / ZoneMult;
    2584             :                 }
    2585      257874 :                 ZoneMassFlowRate += node.MassFlowRate / ZoneMult;
    2586             :             }
    2587             : 
    2588             :             // Do the calculations for the plenum zone
    2589       28951 :         } else if (ZoneRetPlenumAirFlag) {
    2590           0 :             for (int NodeNum = 1; NodeNum <= state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum).NumInletNodes; ++NodeNum) {
    2591           0 :                 auto &node = state.dataLoopNodes->Node(state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum).InletNode(NodeNum));
    2592           0 :                 if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2593           0 :                     CO2MassFlowRate += (node.MassFlowRate * node.CO2) / ZoneMult;
    2594             :                 }
    2595           0 :                 if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2596           0 :                     GCMassFlowRate += (node.MassFlowRate * node.GenContam) / ZoneMult;
    2597             :                 }
    2598           0 :                 ZoneMassFlowRate += node.MassFlowRate / ZoneMult;
    2599             :             }
    2600             :             // add in the leak flow
    2601           0 :             for (int ADUListIndex = 1; ADUListIndex <= state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum).NumADUs; ++ADUListIndex) {
    2602           0 :                 int ADUNum = state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum).ADUIndex(ADUListIndex);
    2603           0 :                 if (state.dataDefineEquipment->AirDistUnit(ADUNum).UpStreamLeak) {
    2604           0 :                     auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(ADUNum);
    2605           0 :                     auto &node = state.dataLoopNodes->Node(airDistUnit.InletNodeNum);
    2606           0 :                     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2607           0 :                         CO2MassFlowRate += (airDistUnit.MassFlowRateUpStrLk * node.CO2) / ZoneMult;
    2608             :                     }
    2609           0 :                     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2610           0 :                         GCMassFlowRate += (airDistUnit.MassFlowRateUpStrLk * node.GenContam) / ZoneMult;
    2611             :                     }
    2612           0 :                     ZoneMassFlowRate += airDistUnit.MassFlowRateUpStrLk / ZoneMult;
    2613             :                 }
    2614           0 :                 if (state.dataDefineEquipment->AirDistUnit(ADUNum).DownStreamLeak) {
    2615           0 :                     auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(ADUNum);
    2616           0 :                     auto &node = state.dataLoopNodes->Node(airDistUnit.OutletNodeNum);
    2617           0 :                     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2618           0 :                         CO2MassFlowRate += (airDistUnit.MassFlowRateDnStrLk * node.CO2) / ZoneMult;
    2619             :                     }
    2620           0 :                     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2621           0 :                         GCMassFlowRate += (airDistUnit.MassFlowRateDnStrLk * node.GenContam) / ZoneMult;
    2622             :                     }
    2623           0 :                     ZoneMassFlowRate += airDistUnit.MassFlowRateDnStrLk / ZoneMult;
    2624             :                 }
    2625             :             }
    2626             : 
    2627       28951 :         } else if (ZoneSupPlenumAirFlag) {
    2628           0 :             auto &node = state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(ZoneSupPlenumNum).InletNode);
    2629           0 :             if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2630           0 :                 CO2MassFlowRate += (node.MassFlowRate * node.CO2) / ZoneMult;
    2631             :             }
    2632           0 :             if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2633           0 :                 GCMassFlowRate += (node.MassFlowRate * node.GenContam) / ZoneMult;
    2634             :             }
    2635           0 :             ZoneMassFlowRate += node.MassFlowRate / ZoneMult;
    2636             :         }
    2637             : 
    2638      393685 :         Real64 SysTimeStepInSeconds = Constant::SecInHour * state.dataHVACGlobal->TimeStepSys;
    2639      393685 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    2640             : 
    2641             :         // Calculate the coefficients for the 3rd order derivative for final
    2642             :         // zone humidity ratio.  The A, B, C coefficients are analogous to the
    2643             :         // CO2 balance.  There are 2 cases that should be considered, system operating and system shutdown.
    2644             : 
    2645      393685 :         Real64 RhoAir = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.ZT, thisZoneHB.airHumRat, RoutineName);
    2646             : 
    2647      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) state.dataContaminantBalance->ZoneAirDensityCO(ZoneNum) = RhoAir;
    2648             :         // Calculate Co2 internal gain
    2649      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) CO2Gain = state.dataContaminantBalance->ZoneCO2Gain(ZoneNum) * RhoAir * 1.0e6;
    2650      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation)
    2651      381637 :             CO2GainExceptPeople = state.dataContaminantBalance->ZoneCO2GainExceptPeople(ZoneNum) * RhoAir * 1.0e6; // Addded for hybrid model
    2652      393685 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation)
    2653      269752 :             GCGain = state.dataContaminantBalance->ZoneGCGain(ZoneNum) * RhoAir * 1.0e6;
    2654             : 
    2655      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2656      381637 :             B = CO2Gain + ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorCO2) +
    2657      381637 :                 (CO2MassFlowRate) + state.dataContaminantBalance->MixingMassFlowCO2(ZoneNum) +
    2658      381637 :                 thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorCO2;
    2659      381637 :             A = ZoneMassFlowRate + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone +
    2660      381637 :                 thisZoneHB.MDotOA;
    2661      748166 :             if (state.afn->multizone_always_simulated ||
    2662      366529 :                 (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    2663           0 :                  state.afn->AirflowNetworkFanActivated)) {
    2664             :                 // Multizone airflow calculated in AirflowNetwork
    2665       15108 :                 B = CO2Gain + (state.afn->exchangeData(ZoneNum).SumMHrCO + state.afn->exchangeData(ZoneNum).SumMMHrCO) + CO2MassFlowRate;
    2666       15108 :                 A = ZoneMassFlowRate + state.afn->exchangeData(ZoneNum).SumMHr + state.afn->exchangeData(ZoneNum).SumMMHr;
    2667             :             }
    2668      381637 :             C = RhoAir * state.dataHeatBal->Zone(ZoneNum).Volume * state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpCO2 / SysTimeStepInSeconds;
    2669             :         }
    2670             : 
    2671      393685 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    2672      381637 :             auto &zoneAirCO2Temp = state.dataContaminantBalance->ZoneAirCO2Temp(ZoneNum);
    2673      381637 :             if (state.afn->distribution_simulated) {
    2674       15108 :                 B += state.afn->exchangeData(ZoneNum).TotalCO2;
    2675             :             }
    2676      381637 :             state.dataContaminantBalance->AZ(ZoneNum) = A;
    2677      381637 :             state.dataContaminantBalance->BZ(ZoneNum) = B;
    2678      381637 :             state.dataContaminantBalance->CZ(ZoneNum) = C;
    2679             : 
    2680             :             // Use a 3rd order derivative to predict final zone CO2 and
    2681             :             // smooth the changes using the zone air capacitance.
    2682      381637 :             switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    2683      381637 :             case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    2684      381637 :                 zoneAirCO2Temp = (B + C * (3.0 * state.dataContaminantBalance->CO2ZoneTimeMinus1Temp(ZoneNum) -
    2685      381637 :                                            (3.0 / 2.0) * state.dataContaminantBalance->CO2ZoneTimeMinus2Temp(ZoneNum) +
    2686      381637 :                                            (1.0 / 3.0) * state.dataContaminantBalance->CO2ZoneTimeMinus3Temp(ZoneNum))) /
    2687      381637 :                                  ((11.0 / 6.0) * C + A);
    2688             :                 // Exact solution
    2689      381637 :             } break;
    2690           0 :             case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    2691           0 :                 if (A == 0.0) { // B=0
    2692           0 :                     zoneAirCO2Temp = state.dataContaminantBalance->ZoneCO21(ZoneNum) + B / C;
    2693             :                 } else {
    2694           0 :                     zoneAirCO2Temp = (state.dataContaminantBalance->ZoneCO21(ZoneNum) - B / A) * std::exp(min(700.0, -A / C)) + B / A;
    2695             :                 }
    2696           0 :             } break;
    2697           0 :             case DataHeatBalance::SolutionAlgo::EulerMethod: {
    2698           0 :                 zoneAirCO2Temp = (C * state.dataContaminantBalance->ZoneCO21(ZoneNum) + B) / (C + A);
    2699           0 :             } break;
    2700           0 :             default:
    2701           0 :                 break;
    2702             :             }
    2703             : 
    2704             :             // Set the CO2 to zero if the zone has been large sinks
    2705      381637 :             if (zoneAirCO2Temp < 0.0) zoneAirCO2Temp = 0.0;
    2706      381637 :             state.dataContaminantBalance->ZoneAirCO2(ZoneNum) = zoneAirCO2Temp;
    2707             : 
    2708      381637 :             if (state.dataHybridModel->FlagHybridModel) {
    2709       19212 :                 if ((state.dataHybridModel->HybridModelZone(ZoneNum).InfiltrationCalc_C ||
    2710       16462 :                      state.dataHybridModel->HybridModelZone(ZoneNum).PeopleCountCalc_C) &&
    2711       35674 :                     (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing)) {
    2712         600 :                     InverseModelCO2(state, ZoneNum, CO2Gain, CO2GainExceptPeople, ZoneMassFlowRate, CO2MassFlowRate, RhoAir);
    2713             :                 }
    2714             :             }
    2715             :             // Now put the calculated info into the actual zone nodes; ONLY if there is zone air flow, i.e. controlled zone or plenum zone
    2716      381637 :             const int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
    2717      381637 :             if (ZoneNodeNum > 0) {
    2718      355698 :                 state.dataLoopNodes->Node(ZoneNodeNum).CO2 = zoneAirCO2Temp;
    2719             :             }
    2720             :         }
    2721             : 
    2722      393685 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2723      269752 :             B = GCGain + ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL) * state.dataContaminantBalance->OutdoorGC) +
    2724      269752 :                 (GCMassFlowRate) + state.dataContaminantBalance->MixingMassFlowGC(ZoneNum) +
    2725      269752 :                 thisZoneHB.MDotOA * state.dataContaminantBalance->OutdoorGC;
    2726      269752 :             A = ZoneMassFlowRate + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.MixingMassFlowZone +
    2727      269752 :                 thisZoneHB.MDotOA;
    2728      527456 :             if (state.afn->multizone_always_simulated ||
    2729      257704 :                 (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
    2730           0 :                  state.afn->AirflowNetworkFanActivated)) {
    2731             :                 // Multizone airflow calculated in AirflowNetwork
    2732       12048 :                 B = GCGain + (state.afn->exchangeData(ZoneNum).SumMHrGC + state.afn->exchangeData(ZoneNum).SumMMHrGC) + GCMassFlowRate;
    2733       12048 :                 A = ZoneMassFlowRate + state.afn->exchangeData(ZoneNum).SumMHr + state.afn->exchangeData(ZoneNum).SumMMHr;
    2734             :             }
    2735      269752 :             C = RhoAir * state.dataHeatBal->Zone(ZoneNum).Volume * state.dataHeatBal->Zone(ZoneNum).ZoneVolCapMultpGenContam / SysTimeStepInSeconds;
    2736             :         }
    2737             : 
    2738      393685 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    2739      269752 :             auto &zoneAirGCTemp = state.dataContaminantBalance->ZoneAirGCTemp(ZoneNum);
    2740      269752 :             if (state.afn->distribution_simulated) {
    2741       12048 :                 B += state.afn->exchangeData(ZoneNum).TotalGC;
    2742             :             }
    2743             : 
    2744      269752 :             state.dataContaminantBalance->AZGC(ZoneNum) = A;
    2745      269752 :             state.dataContaminantBalance->BZGC(ZoneNum) = B;
    2746      269752 :             state.dataContaminantBalance->CZGC(ZoneNum) = C;
    2747             : 
    2748             :             // Use a 3rd order derivative to predict final zone generic contaminant and
    2749             :             // smooth the changes using the zone air capacitance.
    2750      269752 :             switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
    2751      269752 :             case DataHeatBalance::SolutionAlgo::ThirdOrder: {
    2752      269752 :                 zoneAirGCTemp = (B + C * (3.0 * state.dataContaminantBalance->GCZoneTimeMinus1Temp(ZoneNum) -
    2753      269752 :                                           (3.0 / 2.0) * state.dataContaminantBalance->GCZoneTimeMinus2Temp(ZoneNum) +
    2754      269752 :                                           (1.0 / 3.0) * state.dataContaminantBalance->GCZoneTimeMinus3Temp(ZoneNum))) /
    2755      269752 :                                 ((11.0 / 6.0) * C + A);
    2756             :                 // Exact solution
    2757      269752 :             } break;
    2758           0 :             case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
    2759           0 :                 if (A == 0.0) { // B=0
    2760           0 :                     zoneAirGCTemp = state.dataContaminantBalance->ZoneGC1(ZoneNum) + B / C;
    2761             :                 } else {
    2762           0 :                     zoneAirGCTemp = (state.dataContaminantBalance->ZoneGC1(ZoneNum) - B / A) * std::exp(min(700.0, -A / C)) + B / A;
    2763             :                 }
    2764           0 :             } break;
    2765           0 :             case DataHeatBalance::SolutionAlgo::EulerMethod: {
    2766           0 :                 zoneAirGCTemp = (C * state.dataContaminantBalance->ZoneGC1(ZoneNum) + B) / (C + A);
    2767           0 :             } break;
    2768           0 :             default:
    2769           0 :                 break;
    2770             :             }
    2771             : 
    2772             :             // Set the generic contaminant to zero if the zone has been large sinks
    2773      269752 :             if (zoneAirGCTemp < 0.0) zoneAirGCTemp = 0.0;
    2774      269752 :             state.dataContaminantBalance->ZoneAirGC(ZoneNum) = zoneAirGCTemp;
    2775             : 
    2776             :             // Now put the calculated info into the actual zone nodes; ONLY if there is zone air flow, i.e. controlled zone or plenum zone
    2777      269752 :             const int ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
    2778      269752 :             if (ZoneNodeNum > 0) {
    2779      266740 :                 state.dataLoopNodes->Node(ZoneNodeNum).GenContam = zoneAirGCTemp;
    2780             :             }
    2781             :         }
    2782             :     }
    2783       64209 : }
    2784             : 
    2785             : } // namespace EnergyPlus::ZoneContaminantPredictorCorrector

Generated by: LCOV version 1.14