LCOV - code coverage report
Current view: top level - EnergyPlus - ZoneContaminantPredictorCorrector.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1028 1504 68.4 %
Date: 2023-01-17 19:17:23 Functions: 11 12 91.7 %

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

Generated by: LCOV version 1.13